Update most license notices to refer to WWW address
[dejagnu.git] / config / gdb_stub.exp
blob4744fc035b5837d7cc806b44314c8186b093170f
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 } {
25     global gdb_prompt
26     global GDB
27     global tool_root_dir
29     if {![info exists GDB]} then {
30         set GDB "[lookfor_file $tool_root_dir gdb/gdb]"
31         if { $GDB eq "" } {
32             set GDB [transform gdb]
33         }
34     }
36     if {[board_info $dest exists gdb_prompt]} {
37         set gdb_prompt [board_info $dest gdb_prompt]
38     } else {
39         set gdb_prompt {\(gdb\)}
40     }
42     return 1
45 proc gdb_stub_restart { dest } {
46     global gdb_prompt
47     global GDB
49     gdb_stub_init $dest
51     for { set x 1 } { $x < 4 } {incr x} {
52         remote_close $dest
53         sleep 2
54         set command "$GDB -nw -nx"
55         if {[host_info exists gdb_opts]} {
56             append command " [host_info gdb_opts]"
57         }
58         set spawn_id [remote_spawn host $command]
59         remote_expect host 30 {
60             -re $gdb_prompt { }
61         }
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 {
66                     -re $gdb_prompt { }
67                     default {
68                         warning "Error setting baud rate."
69                         return -1
70                     }
71                 }
72             }
75             set value [gdb_stub_startup $dest]
76             if { $value > 0 } {
77                 break
78             }
79             verbose "got $value from gdb_stub_startup"
80             remote_send host "quit\n"
81         }
82         remote_reboot $dest
83     }
84     if { $x < 4 } {
85         global board_info
86         set name [board_info $dest name]
88         set board_info($name,gdb_is_running) 1
89         return 1
90     } else {
91         return 0
92     }
95 proc gdb_stub_remote_check { dest } {
96     global gdb_prompt
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]
102     } else {
103         set serial [board_info $dest netport]
104     }
105     remote_send host "target remote $serial\n"
106     remote_expect host 10 {
107         -re "Couldn't establish connection.*$gdb_prompt" {
108             return 0
109         }
110         -re "Remote debugging.*$gdb_prompt" {
111             verbose "stub is already running"
112             return 1
113         }
114         -re $gdb_prompt {
115             return 0
116         }
117         timeout {
118             remote_send host "\003"
119             remote_expect host 10 {
120                 -re $gdb_prompt { }
121             }
122             return 0
123         }
124         default {
125             return 0
126         }
127     }
130 proc gdb_stub_startup { dest } {
131     global gdb_prompt
132     global GDB
134     set is_running_stub 0
136     if {[gdb_stub_remote_check $dest]} {
137         set is_running_stub 1
138     }
140     if {[board_info $dest exists serial]} {
141         set serial [board_info $dest serial]
142     } else {
143         set serial [board_info $dest netport]
144     }
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"
152                 exp_continue
153             }
154             -re "appears to be alive.*$gdb_prompt" { }
155             -re "Remote target.*connected to.*$gdb_prompt" { }
156             default {
157                 return -1
158             }
159         }
160     }
161     if { $is_running_stub == 0 } {
162         global libdir
164         verbose "building loader"
165         set loader "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]"]
169             } else {
170                 set result [target_compile $libdir/stub-loader.c $loader executable "ldscript=[board_info $dest gdb_stub_ldscript]"]
171             }
172             verbose "result is $result"
173             if {[isremote host]} {
174                 set loader [remote_download host $loader]
175             }
176         }
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"
181                 exp_continue
182             }
183             -re "Load new symbol table.*y or n. $" {
184                 remote_send host "y\n"
185                 exp_continue
186             }
187             -re "Reading symbols from.*done..*$gdb_prompt $" {}
188             -re "$gdb_prompt $" { warning "GDB couldn't find loader" }
189             timeout {
190                 warning "(timeout) read symbol file"
191                 return -1
192             }
193         }
195         if {[board_info $dest exists serial]} {
196             set serial [board_info $dest serial]
197         } else {
198             set serial [board_info $dest netport]
199         }
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" { }
204             -re $gdb_prompt {
205                 warning "Error reconnecting to stub."
206                 return -1
207             }
208             default {
209                 warning "Error reconnecting to stub."
210                 return -1
211             }
212         }
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"
218         } else {
219             remote_send host "load $loader\n"
220         }
221         verbose "Loading $loader into $GDB" 2
222         global verbose
223         set no_run_command 0
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" {
227                 set no_run_command 1
228                 remote_send host "\x03"
229                 sleep 2
230                 remote_send host "\x03"
231                 sleep 1
232             }
233             -re "Loading.*Starting.*at.*$gdb_prompt $" {
234                 verbose "Loaded $loader into $GDB" 1
235                 set no_run_command 1
236             }
237             -re "Loading.*$gdb_prompt $" {
238                 verbose "Loaded $loader into $GDB" 1
239             }
240             -re "$gdb_prompt $"     {
241                 if $verbose>1 then {
242                     warning "GDB couldn't load."
243                 }
244             }
245             timeout {
246                 if $verbose>1 then {
247                     warning "Timed out trying to load $arg."
248                 }
249             }
250         }
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"
257                     exp_continue
258                 }
259                 -re "The program being debugged .*y or n. $" {
260                     remote_send host "y\n"
261                     exp_continue
262                 }
263                 -re "Starting program:.*loader.*$" {
264                     verbose "Starting loader succeeded"
265                 }
266                 timeout {
267                     warning "(timeout) starting the loader"
268                     return -1
269                 }
270                 default {
271                     warning "error starting the loader"
272                 }
273             }
274             sleep 2
275             remote_send host "\x03"
276             sleep 1
277             remote_send host "\x03"
278             verbose "Sent ^C^C"
279             remote_expect host 30 {
280                 -re "Give up .and stop debugging it.*$" {
281                     remote_send host "y\n"
282                     exp_continue
283                 }
284                 -re "$gdb_prompt $" {
285                     verbose "Running loader succeeded"
286                 }
287                 timeout {
288                     warning "(timeout) interrupting the loader"
289                     return -1
290                 }
291                 default {
292                     warning "error interrupting the loader"
293                 }
294             }
295         }
296         remote_send host "quit\n"
297         return [gdb_stub_restart $dest]
298     }
299     return 1
303 # Delete all breakpoints and verify that they were deleted.  If anything
304 # goes wrong we just exit.
306 proc gdb_stub_delete_breakpoints {} {
307     global gdb_prompt
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"
313             exp_continue
314         }
315         -re "$gdb_prompt $" { }
316         timeout { warning "Delete all breakpoints (timeout)" ; return -1}
317     }
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}
323     }
324     return 0
327 proc gdb_stub_go_idle { dest } {
328     gdb_stub_delete_breakpoints
331 proc gdb_stub_add_breakpoint { function args } {
332     global gdb_prompt
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" }
339         default {
340             return "undef"
341         }
342     }
345 proc gdb_stub_start { dest } {
346     global gdb_prompt
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]
351     }
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 {
360         -re $gdb_prompt { }
361     }
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"
365     } else {
366         set start_comm "jump *start\n"
367     }
368     remote_send host "break copyloop\n"
369     remote_expect host 10 {
370         -re "Breakpoint.*$gdb_prompt $" {
371             set start_comm "continue\n"
372         }
373         -re "Function.*not defined.*$gdb_prompt $" { }
374         default { }
375     }
376     remote_send host $start_comm
377     remote_expect host 10 {
378         -re "y or n. $" {
379             remote_send host "y\n"
380             exp_continue
381         }
382         -re "Breakpoint.*in copyloop.*$gdb_prompt $" {
383             remote_send host "jump relocd\n"
384             exp_continue
385         }
386         -re {Continuing at.*[\r\n]} { }
387         default {
388             return { "fail" "" }
389         }
390     }
391     return { "pass" "" }
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"]
398         }
400         set result [gdb_stub_start $dest]
401         if { [lindex $result 0] ne "pass" } {
402             remote_reboot target
403         } else {
404             return 666;         # does anyone use this value?
405         }
406     }
407     return -1
410 proc gdb_stub_wait { dest timeout } {
411     global gdb_prompt
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
421             return [list 0 ""]
422         }
423         -re "Breakpoint.*exit.*=\[1-9\]\[0-9\]*.*$gdb_prompt $" {
424             gdb_stub_go_idle $dest
425             return [list 0 ""]
426         }
427         -re "Breakpoint.*exit.*$gdb_prompt $" {
428             gdb_stub_go_idle $dest
429             return [list 0 ""]
430         }
431         -re "Breakpoint.*abort.*$gdb_prompt $" {
432             gdb_stub_go_idle $dest
433             return [list 1 ""]
434         }
435         -re " EXIT code 0.*$gdb_prompt $" {
436             gdb_stub_go_idle $dest
437             return [list 0 ""]
438         }
439         -re " EXIT code \[1-9]\[0-9]*.*$gdb_prompt $" {
440             gdb_stub_go_idle $dest
441             return [list 0 ""]
442         }
443         -re " EXIT code 4242.*$gdb_prompt $" {
444             gdb_stub_go_idle $dest
445             return [list 1 ""]
446         }
447         -re "Program received.*$gdb_prompt $" {
448             gdb_stub_go_idle $dest
449             return [list 1 ""]
450         }
451         -re "Program exited.*$gdb_prompt $" {
452             gdb_stub_go_idle $dest
453             return [list 1 ""]
454         }
455         -re "Breakpoint $exit_brnum.*$gdb_prompt $" {
456             gdb_stub_go_idle $dest
457             return [list 0 ""]
458         }
459         -re "Breakpoint $abort_brnum.*$gdb_prompt $" {
460             gdb_stub_go_idle $dest
461             return [list 1 ""]
462         }
463         default {
464             remote_close $dest
465             remote_reboot $dest
466             return [list -1 ""]
467         }
468     }
469     return [list -1 ""]
472 proc gdb_stub_load { dest prog args } {
473     global test_timeout
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 wait_timeout 120
484     if {[info exists test_timeout]} {
485         set wait_timeout $test_timeout
486     }
488     verbose -log "Executing on $dest: $prog (timeout = $wait_timeout)" 2
490     set result [remote_spawn $dest $prog]
492     if { $result < 0 } {
493         return [list "fail" "remote_spawn failed"]
494     }
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]
504     } else {
505         global gdb_stub_retry
507         if {![info exists gdb_stub_retry]} {
508             set gdb_stub_retry 1
510             set result [eval gdb_stub_load \{$dest\} \{$prog\} $args]
511             unset gdb_stub_retry
512             return $result
513         } else {
514             return [list "fail" $output]
515         }
516     }
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 } {
526     global gdb_prompt
527     global GDB
529     if {![board_info $dest exists gdb_is_running]} {
530         if {![gdb_stub_restart $dest]} {
531             return 0
532         }
533     }
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"
542             exp_continue
543         }
544         -re "Load new symbol table.*y or n. $" {
545             remote_send host "y\n"
546             exp_continue
547         }
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]
553         }
554         timeout {
555             warning "(timeout) read symbol file"
556             return [gdb_stub_retry_ld $dest $prog]
557         }
558     }
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]
567     } else {
568         set serial [board_info $dest netport]
569     }
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"
575             exp_continue
576         }
577         -re "$gdb_prompt $"     {
578             verbose "Set remote target to $serial" 2
579         }
580         timeout {
581             warning "Couldn't set remote target."
582             return 0
583         }
584     }
586     if {[board_info $dest exists gdb_load_offset]} {
587         set offset "[board_info $dest gdb_load_offset]"
588     } else {
589         set offset ""
590     }
591     remote_send host "load $prog $offset\n"
592     verbose "Loading $prog into $GDB" 2
593     global verbose
594     remote_expect host 1200 {
595         -re "Loading.*$gdb_prompt $" {
596             verbose "Loaded $prog into $GDB" 1
597         }
598         -re "$gdb_prompt $"     {
599             if $verbose>1 then {
600                 warning "GDB couldn't load."
601             }
602         }
603         timeout {
604             if $verbose>1 then {
605                 perror "Timed out trying to load $prog."
606             }
607         }
608     }
609     return 1
613 # Retry the ld operation, but only once.
616 proc gdb_stub_retry_ld { dest prog } {
617     global gdb_stub_retry_ld
619     remote_reboot $dest
620     if {[info exists gdb_stub_retry_ld]} {
621         unset gdb_stub_retry_ld
622         return 0
623     } else {
624         set gdb_stub_retry_ld 1
625     }
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
630     }
631     return $status
634 proc gdb_stub_close { dest } {
635     global board_info
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)
639     }
640     return [remote_close host]
643 set_board_info protocol  "gdb_stub"