# Copyright 2003 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 is a regression test for the following bug, as of 2003-12-12: # # Set a breakpoint which will be hit many times. Attach a complex set # of commands to it, including a "continue" command. Run the program, # so that the breakpoint is hit, its commands get executed, and the # program continues and hits the breakpoint again. You will see # messages like "warning: Invalid control type in command structure.", # or maybe GDB will crash. # # When the breakpoint is hit, bpstat_stop_status copies the # breakpoint's command tree to the bpstat. bpstat_do_actions then # calls execute_control_command to run the commands. The 'continue' # command invokes the following chain of calls: # # continue_command # -> clear_proceed_status # -> bpstat_clear # -> free_command_lines # -> frees the commands we are currently running. # # When control does eventually return to execute_control_command, GDB # continues to walk the tree of freed command nodes, resulting in the # error messages and / or crashes. # # Since this bug depends on storage being reused between the time that # we continue and the time that we fall back to bpstat_do_actions, the # reproduction recipe is more delicate than I would like. I welcome # suggestions for improving this. set prms_id 0 set bug_id 0 set testfile "freebpcmd" set srcfile ${testfile}.c set srcfile1 ${testfile}1.c set binfile ${objdir}/${subdir}/${testfile} if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail." } gdb_exit gdb_start gdb_reinitialize_dir $srcdir/$subdir gdb_load ${binfile} gdb_test "break [gdb_get_line_number "euphonium"]" "" "set breakpoint" # The goal of all this is to make sure that there's plenty of memory # churn, and different amounts of it each time the inferior stops; # this seems to make GDB crash more reliably. set lines {{if (i%2) == 0} {echo "even "} {print i} {else} {echo "odd "} {print i} {end} {set variable $foo = 0} {set variable $j = 0} {while $j < i} {set variable $foo += $j} {set variable $j++} {end} {print $foo} {if i != 40} {c} {end} {end}} send_gdb "commands\n" for {set i 0} {$i < [llength $lines]} {incr i} { gdb_expect { -re ".*>" { send_gdb "[lindex $lines $i]\n" } -re "$gdb_prompt $" { set reason "got top-level prompt early" break } timeout { set reason "timeout" break } } } if {$i >= [llength $lines]} { pass "send breakpoint commands" } else { fail "send breakpoint commands ($reason)" } gdb_run_cmd gdb_test_multiple "" "run program with breakpoint commands" { -re "warning: Invalid control type in command structure" { fail "run program with breakpoint commands" } -re "$gdb_prompt $" { pass "run program with breakpoint commands" } eof { fail "run program with breakpoint commands (GDB died)" } }