URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [gdb-5.3/] [gdb/] [testsuite/] [lib/] [mi-support.exp] - Rev 1181
Go to most recent revision | Compare with Previous | Blame | View Log
# Copyright 1999, 2000 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.# Please email any bugs, comments, and/or additions to this file to:# bug-gdb@prep.ai.mit.edu# This file was based on a file written by Fred Fish. (fnf@cygnus.com)# Test setup routines that work with the MI interpreter.# The variable mi_gdb_prompt is a regexp which matches the gdb mi prompt.# Set it if it is not already set.global mi_gdb_promptif ![info exists mi_gdb_prompt] then {set mi_gdb_prompt "\[(\]gdb\[)\] \r\n"}set MIFLAGS "-i=mi"## mi_gdb_exit -- exit the GDB, killing the target program if necessary#proc mi_gdb_exit {} {catch mi_uncatched_gdb_exit}proc mi_uncatched_gdb_exit {} {global GDBglobal GDBFLAGSglobal verboseglobal gdb_spawn_id;global gdb_promptglobal mi_gdb_promptglobal MIFLAGSgdb_stop_suppressing_tests;if { [info procs sid_exit] != "" } {sid_exit}if ![info exists gdb_spawn_id] {return;}verbose "Quitting $GDB $GDBFLAGS $MIFLAGS"if { [is_remote host] && [board_info host exists fileid] } {send_gdb "999-gdb-exit\n";gdb_expect 10 {-re "y or n" {send_gdb "y\n";exp_continue;}-re "Undefined command.*$gdb_prompt $" {send_gdb "quit\n"exp_continue;}-re "DOSEXIT code" { }default { }}}if ![is_remote host] {remote_close host;}unset gdb_spawn_id}## start gdb -- start gdb running, default procedure## When running over NFS, particularly if running many simultaneous# tests on different hosts all using the same server, things can# get really slow. Give gdb at least 3 minutes to start up.#proc mi_gdb_start { } {global verboseglobal GDBglobal GDBFLAGSglobal gdb_promptglobal mi_gdb_promptglobal timeoutglobal gdb_spawn_id;global MIFLAGSgdb_stop_suppressing_tests;# Start SID.if { [info procs sid_start] != "" } {verbose "Spawning SID"sid_start}verbose "Spawning $GDB -nw $GDBFLAGS $MIFLAGS"if [info exists gdb_spawn_id] {return 0;}if ![is_remote host] {if { [which $GDB] == 0 } then {perror "$GDB does not exist."exit 1}}set res [remote_spawn host "$GDB -nw $GDBFLAGS $MIFLAGS [host_info gdb_opts]"];if { $res < 0 || $res == "" } {perror "Spawning $GDB failed."return 1;}gdb_expect {-re ".*$mi_gdb_prompt$" {verbose "GDB initialized."}-re ".*$gdb_prompt $" {untested "Skip mi tests (got non-mi prompt)."remote_close host;return -1;}-re ".*unrecognized option.*for a complete list of options." {untested "Skip mi tests (not compiled with mi support)."remote_close host;return -1;}-re ".*Interpreter `mi' unrecognized." {untested "Skip mi tests (not compiled with mi support)."remote_close host;return -1;}timeout {perror "(timeout) GDB never initialized after 10 seconds."remote_close host;return -1}}set gdb_spawn_id -1;# FIXME: mi output does not go through pagers, so these can be removed.# force the height to "unlimited", so no pagers get usedsend_gdb "100-gdb-set height 0\n"gdb_expect 10 {-re ".*100-gdb-set height 0\r\n100\\\^done\r\n$mi_gdb_prompt$" {verbose "Setting height to 0." 2}timeout {warning "Couldn't set the height to 0"}}# force the width to "unlimited", so no wraparound occurssend_gdb "101-gdb-set width 0\n"gdb_expect 10 {-re ".*101-gdb-set width 0\r\n101\\\^done\r\n$mi_gdb_prompt$" {verbose "Setting width to 0." 2}timeout {warning "Couldn't set the width to 0."}}return 0;}# Many of the tests depend on setting breakpoints at various places and# running until that breakpoint is reached. At times, we want to start# with a clean-slate with respect to breakpoints, so this utility proc# lets us do this without duplicating this code everywhere.#proc mi_delete_breakpoints {} {global mi_gdb_prompt# FIXME: The mi operation won't accept a prompt back and will use the 'all' argsend_gdb "102-break-delete\n"gdb_expect 30 {-re "Delete all breakpoints.*y or n.*$" {send_gdb "y\n";exp_continue}-re ".*102-break-delete\r\n102\\\^done\r\n$mi_gdb_prompt$" {# This happens if there were no breakpoints}timeout { perror "Delete all breakpoints in delete_breakpoints (timeout)" ; return }}# The correct output is not "No breakpoints or watchpoints." but an# empty BreakpointTable. Also, a query is not acceptable with mi.send_gdb "103-break-list\n"gdb_expect 30 {-re "103-break-list\r\n103\\\^done,BreakpointTable=\{\}\r\n$mi_gdb_prompt$" {}-re "103-break-list\r\n103\\\^done,BreakpointTable=\{nr_rows=\".\",nr_cols=\".\",hdr=\\\[\{width=\".*\",alignment=\".*\",col_name=\"number\",colhdr=\"Num\"\}.*colhdr=\"Type\".*colhdr=\"Disp\".*colhdr=\"Enb\".*colhdr=\"Address\".*colhdr=\"What\".*\\\],body=\\\[\\\]\}" {}-re "103-break-list\r\n103\\\^doneNo breakpoints or watchpoints.\r\n\r\n$mi_gdb_prompt$" {warning "Unexpected console text received"}-re "$mi_gdb_prompt$" { perror "Breakpoints not deleted" ; return }-re "Delete all breakpoints.*or n.*$" {warning "Unexpected prompt for breakpoints deletion";send_gdb "y\n";exp_continue}timeout { perror "-break-list (timeout)" ; return }}}proc mi_gdb_reinitialize_dir { subdir } {global mi_gdb_promptglobal suppress_flagif { $suppress_flag } {return}if [is_remote host] {return "";}send_gdb "104-environment-directory\n"gdb_expect 60 {-re ".*Reinitialize source path to empty.*y or n. " {warning "Got confirmation prompt for dir reinitialization."send_gdb "y\n"gdb_expect 60 {-re "$mi_gdb_prompt$" {}timeout {error "Dir reinitialization failed (timeout)"}}}-re "$mi_gdb_prompt$" {}timeout {error "Dir reinitialization failed (timeout)"}}send_gdb "105-environment-directory $subdir\n"gdb_expect 60 {-re "Source directories searched.*$mi_gdb_prompt$" {verbose "Dir set to $subdir"}-re "105\\\^done\r\n$mi_gdb_prompt$" {# FIXME: We return just the prompt for now.verbose "Dir set to $subdir"# perror "Dir \"$subdir\" failed."}}}## load a file into the debugger.# return a -1 if anything goes wrong.#proc mi_gdb_load { arg } {global verboseglobal loadpathglobal loadfileglobal GDBglobal mi_gdb_promptupvar timeout timeout# ``gdb_unload''# ``gdb_file_cmd''# FIXME: Several of these patterns are only acceptable for console# output. Queries are an error for mi.send_gdb "105-file-exec-and-symbols $arg\n"gdb_expect 120 {-re "Reading symbols from.*done.*$mi_gdb_prompt$" {verbose "\t\tLoaded $arg into the $GDB"# All OK}-re "has no symbol-table.*$mi_gdb_prompt$" {perror "$arg wasn't compiled with \"-g\""return -1}-re "A program is being debugged already.*Kill it.*y or n. $" {send_gdb "y\n"verbose "\t\tKilling previous program being debugged"exp_continue}-re "Load new symbol table from \".*\".*y or n. $" {send_gdb "y\n"gdb_expect 120 {-re "Reading symbols from.*done.*$mi_gdb_prompt$" {verbose "\t\tLoaded $arg with new symbol table into $GDB"# All OK}timeout {perror "(timeout) Couldn't load $arg, other program already loaded."return -1}}}-re "No such file or directory.*$mi_gdb_prompt$" {perror "($arg) No such file or directory\n"return -1}-re "105-file-exec-and-symbols .*\r\n105\\\^done\r\n$mi_gdb_prompt$" {# We are just giving the prompt back for now# All OK}timeout {perror "couldn't load $arg into $GDB (timed out)."return -1}eof {# This is an attempt to detect a core dump, but seems not to# work. Perhaps we need to match .* followed by eof, in which# gdb_expect does not seem to have a way to do that.perror "couldn't load $arg into $GDB (end of file)."return -1}}# ``load''if { [info procs send_target_sid] != "" } {# For SID, things get complexsend_target_sidgdb_expect 60 {-re "\\^done,.*$mi_gdb_prompt$" {}timeout {perror "Unable to connect to SID target"return -1}}send_gdb "48-target-download\n"gdb_expect 10 {-re "48\\^done.*$mi_gdb_prompt$" {}timeout {perror "Unable to download to SID target"return -1}}} elseif { [target_info protocol] == "sim" } {# For the simulator, just connect to it directly.send_gdb "47-target-select sim\n"gdb_expect 10 {-re "47\\^connected.*$mi_gdb_prompt$" {}timeout {perror "Unable to select sim target"return -1}}send_gdb "48-target-download\n"gdb_expect 10 {-re "48\\^done.*$mi_gdb_prompt$" {}timeout {perror "Unable to download to sim target"return -1}}}return 0}# mi_gdb_test COMMAND PATTERN MESSAGE -- send a command to gdb; test the result.## COMMAND is the command to execute, send to GDB with send_gdb. If# this is the null string no command is sent.# PATTERN is the pattern to match for a PASS, and must NOT include# the \r\n sequence immediately before the gdb prompt.# MESSAGE is an optional message to be printed. If this is# omitted, then the pass/fail messages use the command string as the# message. (If this is the empty string, then sometimes we don't# call pass or fail at all; I don't understand this at all.)## Returns:# 1 if the test failed,# 0 if the test passes,# -1 if there was an internal error.#proc mi_gdb_test { args } {global verboseglobal mi_gdb_promptglobal GDB expect_outupvar timeout timeoutif [llength $args]>2 then {set message [lindex $args 2]} else {set message [lindex $args 0]}set command [lindex $args 0]set pattern [lindex $args 1]if [llength $args]==5 {set question_string [lindex $args 3];set response_string [lindex $args 4];} else {set question_string "^FOOBAR$"}if $verbose>2 then {send_user "Sending \"$command\" to gdb\n"send_user "Looking to match \"$pattern\"\n"send_user "Message is \"$message\"\n"}set result -1set string "${command}\n";if { $command != "" } {while { "$string" != "" } {set foo [string first "\n" "$string"];set len [string length "$string"];if { $foo < [expr $len - 1] } {set str [string range "$string" 0 $foo];if { [send_gdb "$str"] != "" } {global suppress_flag;if { ! $suppress_flag } {perror "Couldn't send $command to GDB.";}fail "$message";return $result;}gdb_expect 2 {-re "\[\r\n\]" { }timeout { }}set string [string range "$string" [expr $foo + 1] end];} else {break;}}if { "$string" != "" } {if { [send_gdb "$string"] != "" } {global suppress_flag;if { ! $suppress_flag } {perror "Couldn't send $command to GDB.";}fail "$message";return $result;}}}if [info exists timeout] {set tmt $timeout;} else {global timeout;if [info exists timeout] {set tmt $timeout;} else {set tmt 60;}}gdb_expect $tmt {-re "\\*\\*\\* DOSEXIT code.*" {if { $message != "" } {fail "$message";}gdb_suppress_entire_file "GDB died";return -1;}-re "Ending remote debugging.*$mi_gdb_prompt\[ \]*$" {if ![isnative] then {warning "Can`t communicate to remote target."}gdb_exitgdb_startset result -1}-re "(${question_string})$" {send_gdb "$response_string\n";exp_continue;}-re "Undefined.* command:.*$mi_gdb_prompt\[ \]*$" {perror "Undefined command \"$command\"."fail "$message"set result 1}-re "Ambiguous command.*$mi_gdb_prompt\[ \]*$" {perror "\"$command\" is not a unique command name."fail "$message"set result 1}-re "\[\r\n\]*($pattern)\[\r\n\]+$mi_gdb_prompt\[ \]*$" {if ![string match "" $message] then {pass "$message"}set result 0}-re "Program exited with code \[0-9\]+.*$mi_gdb_prompt\[ \]*$" {if ![string match "" $message] then {set errmsg "$message: the program exited"} else {set errmsg "$command: the program exited"}fail "$errmsg"return -1}-re "The program is not being run.*$mi_gdb_prompt\[ \]*$" {if ![string match "" $message] then {set errmsg "$message: the program is no longer running"} else {set errmsg "$command: the program is no longer running"}fail "$errmsg"return -1}-re ".*$mi_gdb_prompt\[ \]*$" {if ![string match "" $message] then {fail "$message"}set result 1}"<return>" {send_gdb "\n"perror "Window too small."fail "$message"}-re "\\(y or n\\) " {send_gdb "n\n"perror "Got interactive prompt."fail "$message"}eof {perror "Process no longer exists"if { $message != "" } {fail "$message"}return -1}full_buffer {perror "internal buffer is full."fail "$message"}timeout {if ![string match "" $message] then {fail "$message (timeout)"}set result 1}}return $result}## MI run command. (A modified version of gdb_run_cmd)## In patterns, the newline sequence ``\r\n'' is matched explicitly as# ``.*$'' could swallow up output that we attempt to match elsewhere.proc mi_run_cmd {args} {global suppress_flagif { $suppress_flag } {return -1}global mi_gdb_promptif [target_info exists gdb_init_command] {send_gdb "[target_info gdb_init_command]\n";gdb_expect 30 {-re "$mi_gdb_prompt$" { }default {perror "gdb_init_command for target failed";return;}}}if [target_info exists use_gdb_stub] {if [target_info exists gdb,do_reload_on_run] {# Specifying no file, defaults to the executable# currently being debugged.if { [mi_gdb_load ""] < 0 } {return;}send_gdb "000-exec-continue\n";gdb_expect 60 {-re "Continu\[^\r\n\]*\[\r\n\]" {}default {}}return;}if [target_info exists gdb,start_symbol] {set start [target_info gdb,start_symbol];} else {set start "start";}# HACK: Should either use 000-jump or fix the target code# to better handle RUN.send_gdb "jump *$start\n"warning "Using CLI jump command, expect run-to-main FAIL"return}send_gdb "000-exec-run $args\n"gdb_expect {-re "000\\^running\r\n${mi_gdb_prompt}" {}timeout {perror "Unable to start target"return}}# NOTE: Shortly after this there will be a ``000*stopping,...(gdb)''}## Just like run-to-main but works with the MI interface#proc mi_run_to_main { } {global suppress_flagif { $suppress_flag } {return -1}global mi_gdb_promptglobal hexglobal decimalglobal srcdirglobal subdirglobal binfileglobal srcfileset test "mi run-to-main"mi_delete_breakpointsmi_gdb_reinitialize_dir $srcdir/$subdirmi_gdb_load ${binfile}mi_gdb_test "200-break-insert main" \"200\\^done,bkpt=\{number=\"1\",type=\"breakpoint\",disp=\"keep\",enabled=\"y\",addr=\"$hex\",func=\"main\",file=\".*\",line=\"\[0-9\]*\",times=\"0\"\}" \"breakpoint at main"mi_run_cmdgdb_expect {-re "000\\*stopped,reason=\"breakpoint-hit\",bkptno=\"1\",thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\"main\",args=\(\\\[\\\]\|\{\}\),file=\".*\",line=\"\[0-9\]*\"\}\r\n$mi_gdb_prompt$" {pass "$test"return 0}-re ".*$mi_gdb_prompt$" {fail "$test (2)"}timeout {fail "$test (timeout)"return -1}}}# Next to the next statementproc mi_next { test } {global suppress_flagif { $suppress_flag } {return -1}global mi_gdb_promptsend_gdb "220-exec-next\n"gdb_expect {-re "220\\^running\r\n${mi_gdb_prompt}220\\*stopped,reason=\"end-stepping-range\",thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\".*\",args=\[\\\[\{].*[\\\]\}\],file=\".*\",line=\"\[0-9\]*\"\}\r\n$mi_gdb_prompt$" {pass "$test"return 0}timeout {fail "$test"return -1}}}# Step to the next statementproc mi_step { test } {global suppress_flagif { $suppress_flag } {return -1}global mi_gdb_promptsend_gdb "220-exec-step\n"gdb_expect {-re "220\\^running\r\n${mi_gdb_prompt}220\\*stopped,reason=\"end-stepping-range\",thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\".*\",args=\[\\\[\{\].*\[\\\]\}\],file=\".*\",line=\"\[0-9\]*\"\}\r\n$mi_gdb_prompt$" {pass "$test"return 0}timeout {fail "$test"return -1}}}# cmd should not include the number or newline (i.e. "exec-step 3", not# "220-exec-step 3\n"# Can not match -re ".*\r\n${mi_gdb_prompt}", because of false positives# after the first prompt is printed.proc mi_run_to_helper { cmd reason func args file line extra test } {global suppress_flagif { $suppress_flag } {return -1}global mi_gdb_promptglobal hexglobal decimalsend_gdb "220-$cmd\n"gdb_expect {-re "220\\^running\r\n${mi_gdb_prompt}220\\*stopped,reason=\"$reason\",thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\"$func\",args=$args,file=\".*$file\",line=\"$line\"\}$extra\r\n$mi_gdb_prompt$" {pass "$test"return 0}-re "220\\^running\r\n${mi_gdb_prompt}220\\*stopped,reason=\"$reason\",thread-id=\"$decimal\",frame=\{addr=\"$hex\",func=\".*\",args=\[\\\[\{\].*\[\\\]\}\],file=\".*\",line=\"\[0-9\]*\"\}.*\r\n$mi_gdb_prompt$" {fail "$test (stopped at wrong place)"return -1}-re "220\\^running\r\n${mi_gdb_prompt}.*\r\n${mi_gdb_prompt}$" {fail "$test (unknown output after running)"return -1}timeout {fail "$test (timeout)"return -1}}}proc mi_run_to { cmd reason func args file line extra test } {mi_run_to_helper "$cmd" "$reason" "$func" "\\\[$args\\\]" \"$file" "$line" "$extra" "$test"}proc mi_next_to { func args file line test } {mi_run_to "exec-next" "end-stepping-range" "$func" "$args" \"$file" "$line" "" "$test"}proc mi_step_to { func args file line test } {mi_run_to "exec-step" "end-stepping-range" "$func" "$args" \"$file" "$line" "" "$test"}proc mi_finish_to { func args file line result ret test } {mi_run_to "exec-finish" "function-finished" "$func" "$args" \"$file" "$line" \",gdb-result-var=\"$result\",return-value=\"$ret\"" \"$test"}proc mi_continue_to { bkptno func args file line test } {mi_run_to "exec-continue" "breakpoint-hit\",bkptno=\"$bkptno" \"$func" "$args" "$file" "$line" "" "$test"}proc mi0_run_to { cmd reason func args file line extra test } {mi_run_to_helper "$cmd" "$reason" "$func" "\{$args\}" \"$file" "$line" "$extra" "$test"}proc mi0_next_to { func args file line test } {mi0_run_to "exec-next" "end-stepping-range" "$func" "$args" \"$file" "$line" "" "$test"}proc mi0_step_to { func args file line test } {mi0_run_to "exec-step" "end-stepping-range" "$func" "$args" \"$file" "$line" "" "$test"}proc mi0_finish_to { func args file line result ret test } {mi0_run_to "exec-finish" "function-finished" "$func" "$args" \"$file" "$line" \",gdb-result-var=\"$result\",return-value=\"$ret\"" \"$test"}proc mi0_continue_to { bkptno func args file line test } {mi0_run_to "exec-continue" "breakpoint-hit\",bkptno=\"$bkptno" \"$func" "$args" "$file" "$line" "" "$test"}
Go to most recent revision | Compare with Previous | Blame | View Log
