Move C++ internals to prefixed names in dejagnu.h
[dejagnu.git] / config / gdb_stub.exp
blob6ad22a1551f8e031a04f51b824331f9fa2a7a4f3
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 # This file was written by Michael Snyder <msnyder@cygnus.com>.
22 # Stub remote run command.
25 proc gdb_stub_init { dest args } {
26     global gdb_prompt
27     global GDB
28     global tool_root_dir
30     if {![info exists GDB]} then {
31         set GDB "[lookfor_file $tool_root_dir gdb/gdb]"
32         if { $GDB eq "" } {
33             set GDB [transform gdb]
34         }
35     }
37     if {[board_info $dest exists gdb_prompt]} {
38         set gdb_prompt [board_info $dest gdb_prompt]
39     } else {
40         set gdb_prompt {\(gdb\)}
41     }
43     return 1
46 proc gdb_stub_restart { dest } {
47     global gdb_prompt
48     global GDB
50     gdb_stub_init $dest
52     for { set x 1 } { $x < 4 } {incr x} {
53         remote_close $dest
54         sleep 2
55         set command "$GDB -nw -nx"
56         if {[host_info exists gdb_opts]} {
57             append command " [host_info gdb_opts]"
58         }
59         set spawn_id [remote_spawn host $command]
60         remote_expect host 30 {
61             -re $gdb_prompt { }
62         }
63         if { $spawn_id >= 0 } {
64             if {[board_info $dest exists baud]} {
65                 remote_send host "set remotebaud [board_info $dest baud]\n"
66                 remote_expect host 5 {
67                     -re $gdb_prompt { }
68                     default {
69                         warning "Error setting baud rate."
70                         return -1
71                     }
72                 }
73             }
76             set value [gdb_stub_startup $dest]
77             if { $value > 0 } {
78                 break
79             }
80             verbose "got $value from gdb_stub_startup"
81             remote_send host "quit\n"
82         }
83         remote_reboot $dest
84     }
85     if { $x < 4 } {
86         global board_info
87         set name [board_info $dest name]
89         set board_info($name,gdb_is_running) 1
90         return 1
91     } else {
92         return 0
93     }
96 proc gdb_stub_remote_check { dest } {
97     global gdb_prompt
99     if {[board_info $dest exists gdb_serial]} {
100         set serial [board_info $dest gdb_serial]
101     } elseif {[board_info $dest exists serial]} {
102         set serial [board_info $dest serial]
103     } else {
104         set serial [board_info $dest netport]
105     }
106     remote_send host "target remote $serial\n"
107     remote_expect host 10 {
108         -re "Couldn't establish connection.*$gdb_prompt" {
109             return 0
110         }
111         -re "Remote debugging.*$gdb_prompt" {
112             verbose "stub is already running"
113             return 1
114         }
115         -re $gdb_prompt {
116             return 0
117         }
118         timeout {
119             remote_send host "\003"
120             remote_expect host 10 {
121                 -re $gdb_prompt { }
122             }
123             return 0
124         }
125         default {
126             return 0
127         }
128     }
131 proc gdb_stub_startup { dest } {
132     global gdb_prompt
133     global GDB
135     set is_running_stub 0
137     if {[gdb_stub_remote_check $dest]} {
138         set is_running_stub 1
139     }
141     if {[board_info $dest exists serial]} {
142         set serial [board_info $dest serial]
143     } else {
144         set serial [board_info $dest netport]
145     }
147     if { ! $is_running_stub } {
148         set command "target [board_info $dest gdb_protocol] $serial\n"
149         remote_send host $command
150         remote_expect host 5 {
151             -re "already.*y or n." {
152                 remote_send host "y\n"
153                 exp_continue
154             }
155             -re "appears to be alive.*$gdb_prompt" { }
156             -re "Remote target.*connected to.*$gdb_prompt" { }
157             default {
158                 return -1
159             }
160         }
161     }
162     if { $is_running_stub == 0 } {
163         global libdir
165         verbose "building loader"
166         set loader "loader"
167         if {![file exists $loader]} {
168             if {[board_info $dest exists gdb_stub_offset]} {
169                 set result [target_compile $libdir/stub-loader.c $loader executable "libs=-Wl,-Ttext,[board_info $dest gdb_stub_offset]"]
170             } else {
171                 set result [target_compile $libdir/stub-loader.c $loader executable "ldscript=[board_info $dest gdb_stub_ldscript]"]
172             }
173             verbose "result is $result"
174             if {[isremote host]} {
175                 set loader [remote_download host $loader]
176             }
177         }
178         remote_send host "file $loader\n"
179         remote_expect host 20 {
180             -re "A program is being debug.*Kill it.*y or n. $" {
181                 remote_send host "y\n"
182                 exp_continue
183             }
184             -re "Load new symbol table.*y or n. $" {
185                 remote_send host "y\n"
186                 exp_continue
187             }
188             -re "Reading symbols from.*done..*$gdb_prompt $" {}
189             -re "$gdb_prompt $" { warning "GDB couldn't find loader" }
190             timeout {
191                 warning "(timeout) read symbol file"
192                 return -1
193             }
194         }
196         if {[board_info $dest exists serial]} {
197             set serial [board_info $dest serial]
198         } else {
199             set serial [board_info $dest netport]
200         }
201         remote_send host "target [board_info $dest gdb_protocol] $serial\n"
202         remote_expect host 60 {
203             -re "appears to be alive.*$gdb_prompt" { }
204             -re "Remote target.*connected to.*$gdb_prompt" { }
205             -re $gdb_prompt {
206                 warning "Error reconnecting to stub."
207                 return -1
208             }
209             default {
210                 warning "Error reconnecting to stub."
211                 return -1
212             }
213         }
215         # We only send the offset if gdb_load_offset is set. Otherwise, we
216         # assume that sending the offset isn't needed.
217         if {[board_info $dest exists gdb_load_offset]} {
218             remote_send host "load $loader [board_info $dest gdb_stub_offset]\n"
219         } else {
220             remote_send host "load $loader\n"
221         }
222         verbose "Loading $loader into $GDB" 2
223         global verbose
224         set no_run_command 0
225         # FIXME: The value 1200 below should be a parameter.
226         remote_expect host 1200 {
227             -re "Transfer rate:.*Switching to remote protocol.*Remote debugging" {
228                 set no_run_command 1
229                 remote_send host "\x03"
230                 sleep 2
231                 remote_send host "\x03"
232                 sleep 1
233             }
234             -re "Loading.*Starting.*at.*$gdb_prompt $" {
235                 verbose "Loaded $loader into $GDB" 1
236                 set no_run_command 1
237             }
238             -re "Loading.*$gdb_prompt $" {
239                 verbose "Loaded $loader into $GDB" 1
240             }
241             -re "$gdb_prompt $"     {
242                 if $verbose>1 then {
243                     warning "GDB couldn't load."
244                 }
245             }
246             timeout {
247                 if $verbose>1 then {
248                     warning "Timed out trying to load $arg."
249                 }
250             }
251         }
253         if { ! $no_run_command } {
254             remote_send host "run\n"
255             remote_expect host 60 {
256                 -re "A program is being debug.*Kill it.*y or n. $" {
257                     remote_send host "y\n"
258                     exp_continue
259                 }
260                 -re "The program being debugged .*y or n. $" {
261                     remote_send host "y\n"
262                     exp_continue
263                 }
264                 -re "Starting program:.*loader.*$" {
265                     verbose "Starting loader succeeded"
266                 }
267                 timeout {
268                     warning "(timeout) starting the loader"
269                     return -1
270                 }
271                 default {
272                     warning "error starting the loader"
273                 }
274             }
275             sleep 2
276             remote_send host "\x03"
277             sleep 1
278             remote_send host "\x03"
279             verbose "Sent ^C^C"
280             remote_expect host 30 {
281                 -re "Give up .and stop debugging it.*$" {
282                     remote_send host "y\n"
283                     exp_continue
284                 }
285                 -re "$gdb_prompt $" {
286                     verbose "Running loader succeeded"
287                 }
288                 timeout {
289                     warning "(timeout) interrupting the loader"
290                     return -1
291                 }
292                 default {
293                     warning "error interrupting the loader"
294                 }
295             }
296         }
297         remote_send host "quit\n"
298         return [gdb_stub_restart $dest]
299     }
300     return 1
304 # Delete all breakpoints and verify that they were deleted.  If anything
305 # goes wrong we just exit.
307 proc gdb_stub_delete_breakpoints {} {
308     global gdb_prompt
310     remote_send host "delete breakpoints\n"
311     remote_expect host 10 {
312         -re "Delete all breakpoints.*y or n. $" {
313             remote_send host "y\n"
314             exp_continue
315         }
316         -re "$gdb_prompt $" { }
317         timeout { warning "Delete all breakpoints (timeout)" ; return -1}
318     }
319     remote_send host "info breakpoints\n"
320     remote_expect host 10 {
321         -re "No breakpoints or watchpoints..*$gdb_prompt $" {}
322         -re "$gdb_prompt $" { warning "breakpoints not deleted" ; return -1}
323         timeout { warning "info breakpoints (timeout)" ; return -1}
324     }
325     return 0
328 proc gdb_stub_go_idle { dest } {
329     gdb_stub_delete_breakpoints
332 proc gdb_stub_add_breakpoint { function args } {
333     global gdb_prompt
335     remote_send host "break $function\n"
336     remote_expect host 60 {
337         -re "Breakpoint (\[0-9\]+).*$gdb_prompt $" { return $expect_out(1,string) }
338         -re "Function.*not defined.*$gdb_prompt $" { return "undef" }
339         -re "No symbol table.*$gdb_prompt $" { return "undef" }
340         default {
341             return "undef"
342         }
343     }
346 proc gdb_stub_start { dest } {
347     global gdb_prompt
349     set exit_brnum [gdb_stub_add_breakpoint _exit]
350     if { $exit_brnum eq "undef" || [board_info $dest exists always_break_exit] } {
351         set exit_brnum [gdb_stub_add_breakpoint exit]
352     }
353     set abort_brnum [gdb_stub_add_breakpoint abort]
355     upvar #0 gdb_stub_info I
356     set I($dest,exit_brnum) $exit_brnum
357     set I($dest,abort_brnum) $abort_brnum
359     remote_send host "set \$fp=0\n"
360     remote_expect host 10 {
361         -re $gdb_prompt { }
362     }
363     # This is needed for the SparcLite. Whee.
364     if {[board_info $dest exists gdb,start_symbol]} {
365         set start_comm "jump *[board_info $dest gdb,start_symbol]\n"
366     } else {
367         set start_comm "jump *start\n"
368     }
369     remote_send host "break copyloop\n"
370     remote_expect host 10 {
371         -re "Breakpoint.*$gdb_prompt $" {
372             set start_comm "continue\n"
373         }
374         -re "Function.*not defined.*$gdb_prompt $" { }
375         default { }
376     }
377     remote_send host $start_comm
378     remote_expect host 10 {
379         -re "y or n. $" {
380             remote_send host "y\n"
381             exp_continue
382         }
383         -re "Breakpoint.*in copyloop.*$gdb_prompt $" {
384             remote_send host "jump relocd\n"
385             exp_continue
386         }
387         -re {Continuing at.*[\r\n]} { }
388         default {
389             return { "fail" "" }
390         }
391     }
392     return { "pass" "" }
395 proc gdb_stub_spawn { dest prog args } {
396     for { set x 0 } { $x < 3 } { incr x } {
397         if { [remote_ld $dest $prog] != 1 } {
398             return [list "fail" "remote_ld failed"]
399         }
401         set result [gdb_stub_start $dest]
402         if { [lindex $result 0] ne "pass" } {
403             remote_reboot target
404         } else {
405             return 666;         # does anyone use this value?
406         }
407     }
408     return -1
411 proc gdb_stub_wait { dest timeout } {
412     global gdb_prompt
415     upvar #0 gdb_stub_info I
416     set exit_brnum $I($dest,exit_brnum)
417     set abort_brnum $I($dest,abort_brnum)
419     remote_expect host $timeout {
420         -re "Breakpoint.*exit.*=0.*$gdb_prompt $" {
421             gdb_stub_go_idle $dest
422             return [list 0 ""]
423         }
424         -re "Breakpoint.*exit.*=\[1-9\]\[0-9\]*.*$gdb_prompt $" {
425             gdb_stub_go_idle $dest
426             return [list 0 ""]
427         }
428         -re "Breakpoint.*exit.*$gdb_prompt $" {
429             gdb_stub_go_idle $dest
430             return [list 0 ""]
431         }
432         -re "Breakpoint.*abort.*$gdb_prompt $" {
433             gdb_stub_go_idle $dest
434             return [list 1 ""]
435         }
436         -re " EXIT code 0.*$gdb_prompt $" {
437             gdb_stub_go_idle $dest
438             return [list 0 ""]
439         }
440         -re " EXIT code \[1-9]\[0-9]*.*$gdb_prompt $" {
441             gdb_stub_go_idle $dest
442             return [list 0 ""]
443         }
444         -re " EXIT code 4242.*$gdb_prompt $" {
445             gdb_stub_go_idle $dest
446             return [list 1 ""]
447         }
448         -re "Program received.*$gdb_prompt $" {
449             gdb_stub_go_idle $dest
450             return [list 1 ""]
451         }
452         -re "Program exited.*$gdb_prompt $" {
453             gdb_stub_go_idle $dest
454             return [list 1 ""]
455         }
456         -re "Breakpoint $exit_brnum.*$gdb_prompt $" {
457             gdb_stub_go_idle $dest
458             return [list 0 ""]
459         }
460         -re "Breakpoint $abort_brnum.*$gdb_prompt $" {
461             gdb_stub_go_idle $dest
462             return [list 1 ""]
463         }
464         default {
465             remote_close $dest
466             remote_reboot $dest
467             return [list -1 ""]
468         }
469     }
470     return [list -1 ""]
473 proc gdb_stub_load { dest prog args } {
474     global gdb_prompt
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"]
480         }
481     }
483     set result [remote_spawn $dest $prog]
485     if { $result < 0 } {
486         return [list "fail" "remote_spawn failed"]
487     }
489     # FIXME: The value 120 should be a parameter.
490     set result [remote_wait $dest 120]
491     set status [lindex $result 0]
492     set output [lindex $result 1]
494     if { $status == 0 } {
495         return [list "pass" $output]
496     } elseif { $status > 0 } {
497         return [list "fail" $output]
498     } else {
499         global gdb_stub_retry
501         if {![info exists gdb_stub_retry]} {
502             set gdb_stub_retry 1
504             set result [eval gdb_stub_load \{$dest\} \{$prog\} $args]
505             unset gdb_stub_retry
506             return $result
507         } else {
508             return [list "fail" $output]
509         }
510     }
515 # gdb_stub_ld -- load PROG into the board
516 #             Returns a 0 if there was an error,
517 #                       1 if it loaded successfully.
519 proc gdb_stub_ld { dest prog } {
520     global gdb_prompt
521     global GDB
523     if {![board_info $dest exists gdb_is_running]} {
524         if {![gdb_stub_restart $dest]} {
525             return 0
526         }
527     }
529     set loadfile [file tail $prog]
530     set loadpath [file dirname $prog]
532     remote_send host "file $prog\n"
533     remote_expect host 30 {
534         -re "A program is being debug.*Kill it.*y or n. $" {
535             remote_send host "y\n"
536             exp_continue
537         }
538         -re "Load new symbol table.*y or n. $" {
539             remote_send host "y\n"
540             exp_continue
541         }
542         -re "Reading symbols from.*done..*$gdb_prompt $" {}
543         -re "$gdb_prompt $" {
544             # Hmmm...is retrying going to help? I kinda doubt it.
545             warning "GDB couldn't read file"
546             return [gdb_stub_retry_ld $dest $prog]
547         }
548         timeout {
549             warning "(timeout) read symbol file"
550             return [gdb_stub_retry_ld $dest $prog]
551         }
552     }
554     # just in case there are old breakpoints lying around.
555     gdb_stub_delete_breakpoints
557     if {[board_info $dest exists gdb_serial]} {
558         set serial [board_info $dest gdb_serial]
559     } elseif {[board_info $dest exists serial]} {
560         set serial [board_info $dest serial]
561     } else {
562         set serial [board_info $dest netport]
563     }
565     remote_send host "target remote $serial\n"
566     remote_expect host 60 {
567         -re "Kill it?.*y or n.*" {
568             remote_send host "y\n"
569             exp_continue
570         }
571         -re "$gdb_prompt $"     {
572             verbose "Set remote target to $serial" 2
573         }
574         timeout {
575             warning "Couldn't set remote target."
576             return 0
577         }
578     }
580     if {[board_info $dest exists gdb_load_offset]} {
581         set offset "[board_info $dest gdb_load_offset]"
582     } else {
583         set offset ""
584     }
585     remote_send host "load $prog $offset\n"
586     verbose "Loading $prog into $GDB" 2
587     global verbose
588     remote_expect host 1200 {
589         -re "Loading.*$gdb_prompt $" {
590             verbose "Loaded $prog into $GDB" 1
591         }
592         -re "$gdb_prompt $"     {
593             if $verbose>1 then {
594                 warning "GDB couldn't load."
595             }
596         }
597         timeout {
598             if $verbose>1 then {
599                 perror "Timed out trying to load $prog."
600             }
601         }
602     }
603     return 1
607 # Retry the ld operation, but only once.
610 proc gdb_stub_retry_ld { dest prog } {
611     global gdb_stub_retry_ld
613     remote_reboot $dest
614     if {[info exists gdb_stub_retry_ld]} {
615         unset gdb_stub_retry_ld
616         return 0
617     } else {
618         set gdb_stub_retry_ld 1
619     }
620     gdb_stub_restart $dest
621     set status [gdb_stub_ld $dest $prog]
622     if {[info exists gdb_stub_retry_ld]} {
623         unset gdb_stub_retry_ld
624     }
625     return $status
628 proc gdb_stub_close { dest } {
629     global board_info
630     set name [board_info $dest name]
631     if {[info exists board_info($name,gdb_is_running)]} {
632         unset board_info($name,gdb_is_running)
633     }
634     return [remote_close host]
637 set_board_info protocol  "gdb_stub"