| # Test Framework Driver for GDB driving an external simulator |
| # Copyright 1999-2016 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 3 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, see <http://www.gnu.org/licenses/>. |
| |
| load_lib gdb.exp |
| |
| proc sid_start {} { |
| global verbose |
| |
| set port [lindex [split [target_info netport] ":"] 1] |
| |
| # Set a default endianness |
| case [target_info multilib_flags] in { |
| { *big-endian* *-EB* *-meb* } { set sidendian "-EB" } |
| { *little-endian* *-EL* *-mel* } { set sidendian "-EL" } |
| default { |
| if {[target_info exists sim,defaultendian]} then { |
| set sidendian [target_info sim,defaultendian] |
| } else { |
| # rely on endianness settings in sid configuration defaults |
| set sidendian "" |
| } |
| } |
| } |
| case $sidendian in { |
| { -EB } { set sidendian2 {-e "set cpu endian big"} } |
| { -EL } { set sidendian2 {-e "set cpu endian little"} } |
| default { set sidendian2 {} } |
| } |
| |
| # test to see whether to use use sid in build or install tree |
| set use_build_tree [file exists ../../sid] |
| |
| if {$use_build_tree} then { |
| set pre_spawn { |
| global env |
| set env(SID_LIBRARY_PATH) [join [glob "../../sid/component/*"] ":"] |
| set env(SID) "../../sid/main/dynamic/sid" |
| if {! [file exists $env(SID)]} then { error "Cannot find sid in build tree" } |
| } |
| if { [board_info target sim,protocol] == "sid" } { |
| set spawncmd "[target_info sim] [target_info sim,options] $sidendian2 -e \"set cpu-gdb-socket sockaddr-local 0.0.0.0:$port\"" |
| } elseif { [board_info target sim,protocol] == "rawsid" } { |
| set spawncmd "[target_info sim] [target_info sim,options] -$sidendian --gdb=$port" |
| } else { |
| set spawncmd "../../sid/bsp/[target_info sim] $sidendian --gdb=$port [target_info sim,options]" |
| } |
| set post_spawn { |
| global env |
| unset env(SID_LIBRARY_PATH) |
| unset env(SID) |
| } |
| } else { |
| set pre_spawn {} |
| if { [board_info target sim,protocol] == "sid" } { |
| # FIXME: sim,options may be from the build tree, should find |
| # it in the install tree. |
| set spawncmd "sid [target_info sim,options] $sidendian2 -e \"set cpu-gdb-socket sockaddr-local 0.0.0.0:$port\"" |
| } elseif { [board_info target sim,protocol] == "rawsid" } { |
| set spawncmd "[target_info sim] [target_info sim,options] -$sidendian --gdb=$port" |
| } else { |
| set spawncmd "[target_info sim] $sidendian --gdb=$port [target_info sim,options]" |
| } |
| set post_spawn {} |
| } |
| |
| eval $pre_spawn |
| if {[catch [list remote_spawn host $spawncmd] msg]} { |
| perror $msg |
| exit 1 |
| } |
| eval $post_spawn |
| |
| # Don't do the following any more; it breaks with "runtest ... < /dev/null" |
| # expect_background { |
| # -re \[^\n\]*\n { |
| # regsub "\n" $expect_out(buffer) {} msg |
| # verbose "SID: $msg" 2 |
| # } |
| # } |
| |
| # There should be no need to sleep to give SID time to start; |
| # GDB would wait for a fair while for the stub to respond. |
| sleep 4 |
| |
| if ![target_info exists gdb,no_push_conn] { |
| remote_push_conn host |
| } |
| } |
| |
| # |
| # Handle GDB talking to SID |
| # |
| |
| proc gdb_start {} { |
| sid_start |
| return [default_gdb_start] |
| } |
| |
| proc sid_exit {} { |
| if ![target_info exists gdb,no_push_conn] { |
| remote_close host |
| remote_pop_conn host |
| } |
| } |
| |
| proc gdb_exit {} { |
| set result [default_gdb_exit] |
| sid_exit |
| return $result |
| } |
| |
| # |
| # gdb_target_sid |
| # Set gdb to target the simulator |
| # |
| proc send_target_sid { } { |
| # wait a little while, giving sid time to shut down & restart its |
| # gdb socket |
| sleep 4 |
| send_gdb "target [target_info gdb_protocol] [target_info netport]\n" |
| } |
| |
| proc gdb_target_sid { } { |
| global gdb_prompt |
| global exit_status |
| |
| send_target_sid |
| |
| global timeout |
| set prev_timeout $timeout |
| set timeout 60 |
| verbose "Timeout is now $timeout seconds" 2 |
| gdb_expect { |
| -re ".*\[Ee\]rror.*$gdb_prompt $" { |
| perror "Couldn't set target for remote simulator." |
| cleanup |
| gdb_exit |
| } |
| -re "Remote debugging using.*$gdb_prompt" { |
| verbose "Set target to sid" |
| } |
| timeout { |
| perror "Couldn't set target for remote simulator." |
| cleanup |
| gdb_exit |
| } |
| } |
| set timeout $prev_timeout |
| verbose "Timeout is now $timeout seconds" 2 |
| } |
| |
| # |
| # gdb_load -- load a file into the debugger. |
| # return a -1 if anything goes wrong. |
| # |
| proc gdb_load { arg } { |
| global verbose |
| global loadpath |
| global loadfile |
| global GDB |
| global gdb_prompt |
| global retval |
| |
| if { $arg != "" } { |
| if [gdb_file_cmd $arg] then { return -1 } |
| } |
| |
| gdb_target_sid |
| |
| send_gdb "load\n" |
| global timeout |
| set prev_timeout $timeout |
| set timeout 2400 |
| verbose "Timeout is now $timeout seconds" 2 |
| gdb_expect { |
| -re ".*\[Ee\]rror.*$gdb_prompt $" { |
| if $verbose>1 then { |
| perror "Error during download." |
| } |
| set retval -1 |
| } |
| -re ".*$gdb_prompt $" { |
| if $verbose>1 then { |
| send_user "Loaded $arg into $GDB\n" |
| } |
| set retval 0 |
| } |
| -re "$gdb_prompt $" { |
| if $verbose>1 then { |
| perror "GDB couldn't load." |
| } |
| set retval -1 |
| } |
| timeout { |
| if $verbose>1 then { |
| perror "Timed out trying to load $arg." |
| } |
| set retval -1 |
| } |
| } |
| set timeout $prev_timeout |
| verbose "Timeout is now $timeout seconds" 2 |
| return $retval |
| } |