| # Copyright 1996, 1997 Free Software Foundation, Inc. |
| |
| # This program is free software; you can redistribute it and/or modify |
| # it under the terms of the GNU General Public License as published by |
| # the Free Software Foundation; either version 2 of the License, or |
| # (at your option) any later version. |
| # |
| # This program is distributed in the hope that it will be useful, |
| # but WITHOUT ANY WARRANTY; without even the implied warranty of |
| # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| # GNU General Public License for more details. |
| # |
| # You should have received a copy of the GNU General Public License |
| # along with this program; if not, write to the Free Software |
| # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| |
| # This file was written by Michael Snyder <msnyder@cygnus.com>. |
| |
| # GDB support routines for a board using the sparclet remote debugging |
| # protocol. |
| |
| load_lib remote.exp |
| load_lib gdb.exp |
| |
| # |
| # Sparclet remote run command. |
| # |
| |
| proc gdb_start { } { |
| global gdb_prompt |
| |
| if ![file exists loader] { |
| global libdir |
| set loader loader; |
| |
| if [target_info exists gdb_stub_offset] { |
| set result [target_compile "${libdir}/stub-loader.c" $loader executable "libs=-Wl,-Ttext,[target_info gdb_stub_offset]"]; |
| } else { |
| set result [target_compile "${libdir}/stub-loader.c" $loader executable "ldscript=[target_info gdb_stub_ldscript]"]; |
| } |
| } |
| |
| verbose -log "$gdb_prompt is gdb prompt" |
| |
| set result 0; |
| for { set y 0; } { $y < 4 } { incr y } { |
| if { [default_gdb_start] != 0 } { |
| return -1; |
| } |
| |
| if [target_info exists baud] { |
| send_gdb "set remotebaud [target_info baud]\n" |
| gdb_expect { |
| -re "$gdb_prompt" { } |
| default { |
| perror "Error setting baud rate." |
| return -1; |
| } |
| } |
| } |
| |
| for {set x 1;} { $x < 4 } {incr x} { |
| set result [gdb_sparclet_startup $result]; |
| if { $result > 0 } { |
| return 1; |
| } |
| # mmmmm, magic numbers. |
| if { $result == -42 || $result == -43 } { |
| break; |
| } else { |
| reboot_target; |
| } |
| } |
| if { $x == 4 } { |
| return -1; |
| } |
| gdb_exit; |
| sleep 5; |
| } |
| return -1; |
| } |
| |
| proc gdb_sparclet_startup { arg } { |
| global gdb_prompt |
| global GDB |
| global verbose |
| |
| set is_running_stub 0; |
| |
| if [target_info exists serial] { |
| set serial [target_info serial]; |
| } else { |
| set serial [target_info netport]; |
| } |
| set protocol [target_info gdb_protocol]; |
| set check_stub 1; |
| if { $arg != -42 } { |
| send_gdb "target $protocol $serial\n"; |
| # 10 seconds may be a bit short. |
| gdb_expect 10 { |
| -re "already.*y or n." { |
| gdb_send "y\n"; |
| exp_continue; |
| } |
| -re "Remote target.*connected to.*$gdb_prompt" { set check_stub 0; } |
| -re "$gdb_prompt" { } |
| timeout { } |
| } |
| if { $check_stub } { |
| verbose "timed out, checking if stub is already running" |
| send_gdb "\003"; |
| sleep 1; |
| send_gdb "\003"; |
| gdb_expect 10 { |
| -re "$gdb_prompt" { } |
| default { |
| remote_close host; |
| return -42; |
| } |
| } |
| } |
| } |
| if [target_info exists gdb_serial] { |
| set gdb_serial [target_info gdb_serial]; |
| } else { |
| set gdb_serial $serial; |
| } |
| if { $check_stub } { |
| send_gdb "target remote $gdb_serial\n"; |
| gdb_expect 15 { |
| -re "Remote debugging.*$gdb_prompt" { |
| verbose "stub is already running" |
| set is_running_stub 1; |
| } |
| default { |
| warning "board isn't responding"; |
| remote_close host; |
| remote_reboot target; |
| return -43; |
| } |
| } |
| } |
| |
| if { $is_running_stub == 0 } { |
| global srcdir |
| |
| if [is_remote host] { |
| set loader [remote_download host "loader"]; |
| } else { |
| set loader "loader"; |
| } |
| send_gdb "file $loader\n"; |
| gdb_expect { |
| -re "A program is being debug.*Kill it.*y or n. $" { |
| send_gdb "y\n" |
| exp_continue |
| } |
| -re "Load new symbol table.*y or n. $" { |
| send_gdb "y\n" |
| exp_continue |
| } |
| -re "Reading symbols from.*done..*$gdb_prompt $" {} |
| -re "$gdb_prompt $" { perror "GDB couldn't find loader" } |
| timeout { |
| perror "(timeout) read symbol file" ; |
| return -1 |
| } |
| } |
| |
| send_gdb "target $protocol $serial\n"; |
| gdb_expect { |
| -re "Remote target.*connected to.*$gdb_prompt" { } |
| default { |
| perror "Error reconnecting to board."; |
| return -1; |
| } |
| } |
| |
| send_gdb "load $loader [target_info gdb_stub_offset]\n" |
| verbose "Loading $loader into $GDB" 2 |
| set no_run_command 0; |
| gdb_expect 1200 { |
| -re "Loading.*$gdb_prompt $" { |
| verbose "Loaded $loader into $GDB" 1 |
| } |
| -re "Transfer rate:.*Switching to remote protocol.*Remote debugging" { |
| set no_run_command 1; |
| } |
| -re "$gdb_prompt $" { |
| if $verbose>1 then { |
| perror "GDB couldn't load." |
| } |
| } |
| timeout { |
| if $verbose>1 then { |
| perror "Timed out trying to load $arg." |
| } |
| } |
| } |
| |
| if !$no_run_command { |
| send_gdb "run\n"; |
| gdb_expect 60 { |
| -re "A program is being debug.*Kill it.*y or n. $" { |
| send_gdb "y\n" |
| exp_continue |
| } |
| -re "The program being debugged .*y or n. $" { |
| send_gdb "y\n" |
| exp_continue |
| } |
| -re "Starting program:.*loader.*$" { |
| verbose "Starting loader succeeded" |
| } |
| timeout { |
| perror "(timeout) starting the loader" ; |
| return -1 |
| } |
| default { |
| perror "error starting the loader"; |
| } |
| } |
| } |
| sleep 2; |
| send_gdb "" |
| sleep 1; |
| send_gdb "" |
| verbose "Sent ^C^C" |
| gdb_expect 10 { |
| -re "Give up .and stop debugging it.*$" { |
| send_gdb "y\n" |
| exp_continue |
| } |
| -re "$gdb_prompt $" { |
| verbose "Running loader succeeded" |
| } |
| timeout { |
| warning "(timeout) interrupting the loader" ; |
| remote_close host; |
| } |
| default { |
| warning "error interrupting the loader"; |
| } |
| } |
| |
| gdb_exit; |
| return [gdb_start]; |
| } |
| return 1; |
| } |
| |
| proc gdb_run_cmd { args } { |
| global gdb_prompt |
| |
| gdb_breakpoint exit; |
| send_gdb "set \$fp=0\n"; |
| gdb_expect { |
| -re "$gdb_prompt" { } |
| } |
| # This is needed for the SparcLite. Whee. |
| if [target_info exists gdb,start_symbol] { |
| set start_comm "jump *[target_info gdb,start_symbol]\n"; |
| } else { |
| set start_comm "jump *start\n"; |
| } |
| send_gdb "break copyloop\n"; |
| gdb_expect 10 { |
| -re "Breakpoint.*$gdb_prompt $" { |
| set start_comm "continue\n"; |
| } |
| -re "$gdb_prompt $" { } |
| timeout { warning "break copyloop failed badly"; } |
| } |
| send_gdb $start_comm; |
| gdb_expect 10 { |
| -re "y or n. $" { |
| remote_send host "y\n" |
| exp_continue; |
| } |
| -re "Breakpoint.*in copyloop.*$gdb_prompt $" { |
| remote_send host "jump relocd\n"; |
| exp_continue; |
| } |
| -re "Continuing at.*\[\r\n\]" { } |
| default { |
| return -1; |
| } |
| } |
| |
| return ""; |
| } |
| |
| |
| # |
| # gdb_load -- load a file into the GDB. |
| # Returns a 0 if there was an error, |
| # 1 if it load successfully. |
| # |
| proc gdb_load { arg } { |
| global verbose |
| global loadpath |
| global loadfile |
| global gdb_prompt |
| global GDB |
| global expect_out |
| |
| set loadfile [file tail $arg] |
| set loadpath [file dirname $arg] |
| |
| set protocol [target_info gdb_protocol]; |
| |
| if [is_remote host] { |
| set arg [remote_download host $arg]; |
| } |
| send_gdb "file $arg\n" |
| gdb_expect 30 { |
| -re "A program is being debug.*Kill it.*y or n. $" { |
| send_gdb "y\n" |
| exp_continue |
| } |
| -re "Load new symbol table.*y or n. $" { |
| send_gdb "y\n" |
| exp_continue |
| } |
| -re "Reading symbols from.*done..*$gdb_prompt $" {} |
| -re "$gdb_prompt $" { perror "GDB couldn't read file" } |
| timeout { |
| perror "(timeout) read symbol file" ; |
| return -1 |
| } |
| } |
| |
| if [target_info exists gdb_serial] { |
| set gdb_serial [target_info gdb_serial]; |
| } else { |
| if [target_info exists serial] { |
| set gdb_serial [target_info serial]; |
| } else { |
| set gdb_serial [target_info netport]; |
| } |
| } |
| send_gdb "target remote $gdb_serial\n" |
| gdb_expect 30 { |
| -re "Kill it?.*y or n.*" { |
| send_gdb "y\n"; |
| exp_continue |
| } |
| -re "$gdb_prompt $" { |
| verbose "Set remote target to $gdb_serial" 2 |
| } |
| timeout { |
| perror "Couldn't set remote target." |
| return -1 |
| } |
| } |
| if [target_info exists gdb_load_offset] { |
| set offset "[target_info gdb_load_offset]"; |
| } else { |
| set offset ""; |
| } |
| send_gdb "load $arg $offset\n" |
| verbose "Loading $arg into $GDB" 2 |
| gdb_expect 1200 { |
| -re "Loading.*$gdb_prompt $" { |
| verbose "Loaded $arg into $GDB" 1 |
| } |
| -re "$gdb_prompt $" { |
| if $verbose>1 then { |
| perror "GDB couldn't load." |
| } |
| } |
| timeout { |
| if $verbose>1 then { |
| perror "Timed out trying to load $arg." |
| } |
| } |
| } |
| send_gdb "list main\n"; |
| gdb_expect 60 { |
| -re "$gdb_prompt" { } |
| default { |
| perror "command for list main never completed"; |
| return -1; |
| } |
| } |
| |
| return 0 |
| } |