diff options
Diffstat (limited to 'gdb/testsuite/gdb.multi/pending-bp.exp')
-rw-r--r-- | gdb/testsuite/gdb.multi/pending-bp.exp | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.multi/pending-bp.exp b/gdb/testsuite/gdb.multi/pending-bp.exp index 13f76f4..2a0644b 100644 --- a/gdb/testsuite/gdb.multi/pending-bp.exp +++ b/gdb/testsuite/gdb.multi/pending-bp.exp @@ -72,6 +72,48 @@ proc do_test_setup { inf_1_stop inf_2_stop } { return true } +# Create a breakpoint on the function 'foo' in THREAD. It is expected +# that the breakpoint created will be pending, this is checked by +# running the 'info breakpoints' command. +# +# Returns the number for the newly created breakpoint. +proc do_create_pending_foo_breakpoint { {thread "1.1"} } { + gdb_test "break foo thread $thread" \ + [multi_line \ + "Function \"foo\" not defined\\." \ + "Breakpoint $::decimal \\(foo\\) pending\."] \ + "set pending thread-specific breakpoint" + set bpnum [get_integer_valueof "\$bpnum" "*INVALID*" \ + "get number for thread-specific breakpoint on foo"] + gdb_test "info breakpoints $bpnum" \ + [multi_line \ + "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+foo" \ + "\\s+stop only in thread [string_to_regexp $thread]"] \ + "check thread-specific breakpoint is initially pending" + + return $bpnum +} + +# Create a breakpoint on the function 'foo' in THREAD. It is expected +# that the breakpoint created will not be pending, this is checked by +# running the 'info breakpoints' command. +# +# Returns the number for the newly created breakpoint. +proc do_create_foo_breakpoint { {thread "1.1"} } { + gdb_test "break foo thread $thread" \ + "Breakpoint $::decimal at $::hex" \ + "set thread-specific breakpoint" + set bpnum [get_integer_valueof "\$bpnum" "*INVALID*" \ + "get number for thread-specific breakpoint on foo"] + gdb_test "info breakpoints $bpnum" \ + [multi_line \ + "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$::hex\\s+<foo\[^>\]*> inf $::decimal" \ + "\\s+stop only in thread [string_to_regexp $thread]"] \ + "check thread-specific breakpoint is initially pending" + + return $bpnum +} + # Check that when a breakpoint is in the pending state, but that breakpoint # does have some locations (those locations themselves are pending), GDB # doesn't display the inferior list in the 'info breakpoints' output. @@ -122,5 +164,169 @@ proc_with_prefix test_no_inf_display {} { "check info breakpoints while breakpoint is pending" } +# Setup two inferiors. In #1 the symbol 'foo' has not yet been +# loaded, while in #2 the symbol 'foo' has been loaded. +# +# Create a thread-specific breakpoint on 'foo' tied to a thread in +# inferior #1, the breakpoint should be pending -- 'foo' is not yet +# loaded in #1. +# +# Now move inferior #1 forward until 'foo' is loaded, check the +# breakpoint is no longer pending. +# +# Move inferior #1 forward more until 'foo' is unloaded, check that +# the breakpoint returns to the pending state. +proc_with_prefix test_pending_toggle { } { + + do_test_setup "Break before open" "Break before close" + + set bpnum [do_create_pending_foo_breakpoint] + + # Now return to inferior 1 and continue until the shared library is + # loaded, the breakpoint should become non-pending. + gdb_test "inferior 1" "Switching to inferior 1 .*" \ + "switch back to inferior 1" + gdb_continue_to_breakpoint "stop in foo in inferior 1" "foo \\(\\) .*" + + gdb_test "info breakpoint $bpnum" \ + [multi_line \ + "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$::hex <foo\[^>\]*> inf 1" \ + "\\s+stop only in thread 1\\.1" \ + "\\s+breakpoint already hit 1 time"] \ + "check thread-specific breakpoint is no longer pending" + + gdb_breakpoint [gdb_get_line_number "Break after close"] temporary + gdb_continue_to_breakpoint "close library" + gdb_test "info breakpoints $bpnum" \ + [multi_line \ + "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+foo" \ + "\\s+stop only in thread 1\\.1" \ + "\\s+breakpoint already hit 1 time"] \ + "check thread-specific breakpoint is pending again" +} + +# Create a Python variable VAR and set it to the gdb.Breakpoint object +# corresponding to the breakpoint numbered BPNUM. If THREAD is not +# the empty string then THREAD should be an integer, check that +# gdb.Breakpoint.thread is set to the value of THREAD. Otherwise, if +# THREAD is the empty string, check that gdb.Breakpoint.thread is set +# to None. +proc py_find_breakpoint { var bpnum {thread ""} } { + gdb_test_no_output \ + "python ${var}=\[b for b in gdb.breakpoints() if b.number == $bpnum\]\[0\]" \ + "find Python gdb.Breakpoint object" + if { $thread ne "" } { + gdb_test_no_output "python assert(${var}.thread == ${thread})" \ + "check thread attribute is currently correct" + } else { + gdb_test_no_output "python assert(${var}.thread is None)" \ + "check thread attribute is currently correct" + } +} + +# Setup two inferiors. In #1 the symbol 'foo' has not yet been +# loaded, while in #2 the symbol 'foo' has been loaded. +# +# Create a thread-specific breakpoint on 'foo' tied to a thread in +# inferior #1, the breakpoint should be pending -- 'foo' is not yet +# loaded in #1. +# +# Use Python to change the thread of the thread-specific breakpoint to +# a thread in inferior #2, at this point the thread should gain a +# location and become non-pending. +# +# Set the thread back to a thread in inferior #1, the breakpoint +# should return to the pending state. +proc_with_prefix py_test_toggle_thread {} { + do_test_setup "Break before open" "Break after open" + + set bpnum [do_create_pending_foo_breakpoint] + + py_find_breakpoint "bp" $bpnum 1 + + gdb_test_no_output "python bp.thread = 2" \ + "change thread on thread-specific breakpoint" + gdb_test "info breakpoint $bpnum" \ + [multi_line \ + "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$::hex <foo\[^>\]*> inf 2" \ + "\\s+stop only in thread 2\\.1"] \ + "check thread-specific breakpoint now has a location" + + gdb_test_no_output "set call_count = 2" "set call_count in inferior 2" + gdb_continue_to_breakpoint "stop at foo in inferior 2" "foo \\(\\) .*" + + gdb_test_no_output "python bp.thread = 1" \ + "restore thread on thread-specific breakpoint" + gdb_test "info breakpoints $bpnum" \ + [multi_line \ + "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+foo" \ + "\\s+stop only in thread 1\\.1" \ + "\\s+breakpoint already hit 1 time"] \ + "check thread-specific breakpoint has returned to pending" + + gdb_breakpoint [gdb_get_line_number "Break after close"] temporary + gdb_continue_to_breakpoint "stop after close in inferior 2" \ + ".* Break after close\\. .*" + + gdb_test "inferior 1" "Switching to inferior 1 .*" \ + "switch to inferior 1" + gdb_continue_to_breakpoint "stop at foo in inferior 1" "foo \\(\\) .*" +} + +# Setup two inferiors. Both inferiors have the symbol 'foo' +# available. +# +# Create a thread-specific breakpoint on 'foo' tied to a thread in +# inferior #1, the breakpoint should not be pending, but will only +# have a single location, the location in inferior #1. +# +# Use Python to change the thread of the thread-specific breakpoint to +# None. At this point the breakpoint should gain a second location, a +# location in inferior #2. +proc_with_prefix py_test_clear_thread {} { + do_test_setup "Break after open" "Break after open" + + set bpnum [do_create_foo_breakpoint] + + py_find_breakpoint "bp" $bpnum 1 + + gdb_test_no_output "python bp.thread = None" \ + "clear thread on thread-specific breakpoint" + gdb_test "info breakpoints $bpnum" \ + [multi_line \ + "${bpnum}\\s+breakpoint\\s+keep y\\s+<MULTIPLE>\\s*" \ + "${bpnum}\\.1\\s+y\\s+${::hex}\\s+<foo\[^>\]*> inf $::decimal" \ + "${bpnum}\\.2\\s+y\\s+${::hex}\\s+<foo\[^>\]*> inf $::decimal"] \ + "check for a location in both inferiors" + + gdb_continue_to_breakpoint "stop at foo in inferior 2" "foo \\(\\) .*" + gdb_test_no_output "set call_count = 2" "set call_count in inferior 2" + + gdb_test "inferior 1" "Switching to inferior 1 .*" \ + "switch to inferior 1" + gdb_continue_to_breakpoint "stop at foo in inferior 1" "foo \\(\\) .*" + gdb_test_no_output "set call_count = 2" "set call_count in inferior 1" + + gdb_test_no_output "python bp.thread = 2" + gdb_test "info breakpoints $bpnum" \ + [multi_line \ + "${bpnum}\\s+breakpoint\\s+keep y\\s+${::hex}\\s+<foo\[^>\]*> inf 2" \ + "\\s+stop only in thread 2\\.1" \ + "\\s+breakpoint already hit 2 times"] \ + "check for a location only in inferior 2" + + gdb_breakpoint [gdb_get_line_number "Break after close"] temporary + gdb_continue_to_breakpoint "stop after close in inferior 1" \ + ".* Break after close\\. .*" + + gdb_test "inferior 2" "Switching to inferior 2 .*" \ + "switch back to inferior 2" + gdb_continue_to_breakpoint "stop at foo again in inferior 2" \ + "foo \\(\\) .*" +} + # Run all the tests. test_no_inf_display +test_pending_toggle +py_test_toggle_thread +py_test_clear_thread |