Remove obsolete test from gdb.cp/var-tag.exp
[binutils-gdb.git] / gdb / testsuite / gdb.threads / infcall-from-bp-cond-simple.exp
blobc9508c9d67ea8a4db57a5e606978de8a04af74b1
1 # Copyright 2022-2024 Free Software Foundation, Inc.
3 # This program is free software; you can redistribute it and/or modify
4 # it under the terms of the GNU General Public License as published by
5 # the Free Software Foundation; either version 3 of the License, or
6 # (at your option) any later version.
8 # This program is distributed in the hope that it will be useful,
9 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 # GNU General Public License for more details.
13 # You should have received a copy of the GNU General Public License
14 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 # Some simple tests of inferior function calls from breakpoint
17 # conditions, in multi-threaded inferiors.
19 # This test sets up a multi-threaded inferior, and places a breakpoint
20 # at a location that many of the threads will reach.  We repeat the
21 # test with different conditions, sometimes a single thread should
22 # stop at the breakpoint, sometimes multiple threads should stop, and
23 # sometimes no threads should stop.
25 standard_testfile
27 if { [build_executable "failed to prepare" ${binfile} "${srcfile}" \
28           {debug pthreads}] == -1 } {
29     return
32 set cond_bp_line [gdb_get_line_number "Breakpoint here"]
33 set stop_bp_line [gdb_get_line_number "Stop marker"]
34 set nested_bp_line [gdb_get_line_number "Nested breakpoint"]
35 set segv_line [gdb_get_line_number "Segfault happens here"]
37 # Start GDB based on TARGET_ASYNC and TARGET_NON_STOP, and then runto main.
38 proc start_gdb_and_runto_main { target_async target_non_stop } {
39     save_vars { ::GDBFLAGS } {
40         append ::GDBFLAGS \
41             " -ex \"maint set target-non-stop $target_non_stop\""
42         append ::GDBFLAGS \
43             " -ex \"maintenance set target-async ${target_async}\""
45         clean_restart ${::binfile}
46     }
48     if { ![runto_main] } {
49         return -1
50     }
52     return 0
55 # Run a test of GDB's conditional breakpoints, where the conditions include
56 # inferior function calls.
58 # CONDITION is the expression to be used as the breakpoint condition.
60 # N_EXPECTED_HITS is the number of threads that we expect to stop due to
61 # CONDITON.
63 # MESSAGE is used as a test name prefix.
64 proc run_condition_test { message n_expected_hits condition \
65                               target_async target_non_stop } {
66     with_test_prefix $message {
68         if { [start_gdb_and_runto_main $target_async \
69                   $target_non_stop] == -1 } {
70             return
71         }
73         # Use this convenience variable to track how often the
74         # breakpoint condition has been evaluated.  This should be
75         # once per thread.
76         gdb_test "set \$n_cond_eval = 0"
78         # Setup the conditional breakpoint.
79         gdb_breakpoint \
80             "${::srcfile}:${::cond_bp_line} if ((++\$n_cond_eval) && (${condition}))"
82         # And a breakpoint that we hit when the test is over, this one is
83         # not conditional.  Only the main thread gets here once all the
84         # other threads have finished.
85         gdb_breakpoint "${::srcfile}:${::stop_bp_line}"
87         # The number of times we stop at the conditional breakpoint.
88         set n_hit_condition 0
90         # Now keep 'continue'-ing GDB until all the threads have finished
91         # and we reach the stop_marker breakpoint.
92         gdb_test_multiple "continue" "spot all breakpoint hits" {
93             -re " worker_func \[^\r\n\]+${::srcfile}:${::cond_bp_line}\r\n${::decimal}\\s+\[^\r\n\]+Breakpoint here\[^\r\n\]+\r\n${::gdb_prompt} $" {
94                 incr n_hit_condition
95                 send_gdb "continue\n"
96                 exp_continue
97             }
99             -re " stop_marker \[^\r\n\]+${::srcfile}:${::stop_bp_line}\r\n${::decimal}\\s+\[^\r\n\]+Stop marker\[^\r\n\]+\r\n${::gdb_prompt} $" {
100                 pass $gdb_test_name
101             }
102         }
104         gdb_assert { $n_hit_condition == $n_expected_hits } \
105             "stopped at breakpoint the expected number of times"
107         # Ensure the breakpoint condition was evaluated once per thread.
108         gdb_test "print \$n_cond_eval" "= 3" \
109             "condition was evaluated in each thread"
110     }
113 # Check that after handling a conditional breakpoint (where the condition
114 # includes an inferior call), it is still possible to kill the running
115 # inferior, and then restart the inferior.
117 # At once point doing this would result in GDB giving an assertion error.
118 proc_with_prefix run_kill_and_restart_test { target_async target_non_stop } {
119     # This test relies on the 'start' command, which is not possible with
120     # the plain 'remote' target.
121     if { [target_info gdb_protocol] == "remote" } {
122         return
123     }
125     if { [start_gdb_and_runto_main $target_async \
126               $target_non_stop] == -1 } {
127         return
128     }
130     # Setup the conditional breakpoint.
131     gdb_breakpoint \
132         "${::srcfile}:${::cond_bp_line} if (is_matching_tid (arg, 1))"
133     gdb_continue_to_breakpoint "worker_func"
135     # Now kill the program being debugged.
136     gdb_test "kill" "" "kill process" \
137         "Kill the program being debugged.*y or n. $" "y"
139     # Check we can restart the inferior.  At one point this would trigger an
140     # assertion.
141     gdb_start_cmd
144 # Create a conditional breakpoint which includes a call to a function that
145 # segfaults.  Run GDB and check what happens when the inferior segfaults
146 # during the inferior call.
147 proc_with_prefix run_bp_cond_segfaults { target_async target_non_stop } {
148     if { [start_gdb_and_runto_main $target_async \
149               $target_non_stop] == -1 } {
150         return
151     }
153     # This test relies on the inferior segfaulting when trying to
154     # access address zero.
155     if { [is_address_zero_readable] } {
156         return
157     }
159     # Setup the conditional breakpoint, include a call to
160     # 'function_that_segfaults', which triggers the segfault.
161     gdb_breakpoint \
162         "${::srcfile}:${::cond_bp_line} if (is_matching_tid (arg, 0) && function_that_segfaults ())"
163     set bp_1_num [get_integer_valueof "\$bpnum" "*UNKNOWN*" \
164                       "get number of conditional breakpoint"]
166     gdb_test "continue" \
167         [multi_line \
168              "Continuing\\." \
169              ".*" \
170              "Thread ${::decimal} \"infcall-from-bp\" received signal SIGSEGV, Segmentation fault\\." \
171              "${::hex} in function_that_segfaults \\(\\) at \[^\r\n\]+:${::segv_line}" \
172              "${::decimal}\\s+\[^\r\n\]+Segfault happens here\[^\r\n\]+" \
173              "Error in testing condition for breakpoint ${bp_1_num}:" \
174              "The program being debugged was signaled while in a function called from GDB\\." \
175              "GDB remains in the frame where the signal was received\\." \
176              "To change this behavior use \"set unwind-on-signal on\"\\." \
177              "Evaluation of the expression containing the function" \
178              "\\(function_that_segfaults\\) will be abandoned\\." \
179              "When the function is done executing, GDB will silently stop\\."]
182 # Create a conditional breakpoint which includes a call to a function that
183 # itself has a breakpoint set within it.  Run GDB and check what happens
184 # when GDB hits the nested breakpoint.
185 proc_with_prefix run_bp_cond_hits_breakpoint { target_async target_non_stop } {
186     if { [start_gdb_and_runto_main $target_async \
187               $target_non_stop] == -1 } {
188         return
189     }
191     # Setup the conditional breakpoint, include a call to
192     # 'function_with_breakpoint' in which we will shortly place a
193     # breakpoint.
194     gdb_breakpoint \
195         "${::srcfile}:${::cond_bp_line} if (is_matching_tid (arg, 0) && function_with_breakpoint ())"
196     set bp_1_num [get_integer_valueof "\$bpnum" "*UNKNOWN*" \
197                       "get number of conditional breakpoint"]
199     gdb_breakpoint "${::srcfile}:${::nested_bp_line}"
200     set bp_2_num [get_integer_valueof "\$bpnum" "*UNKNOWN*" \
201                       "get number of nested breakpoint"]
203     gdb_test "continue" \
204         [multi_line \
205              "Continuing\\." \
206              ".*" \
207              "Thread ${::decimal} \"infcall-from-bp\" hit Breakpoint ${bp_2_num}, function_with_breakpoint \\(\\) at \[^\r\n\]+:${::nested_bp_line}" \
208              "${::decimal}\\s+\[^\r\n\]+Nested breakpoint\[^\r\n\]+" \
209              "Error in testing condition for breakpoint ${bp_1_num}:" \
210              "The program being debugged stopped while in a function called from GDB\\." \
211              "Evaluation of the expression containing the function" \
212              "\\(function_with_breakpoint\\) will be abandoned\\." \
213              "When the function is done executing, GDB will silently stop\\."]
216 foreach_with_prefix target_async { "on" "off" } {
217     foreach_with_prefix target_non_stop { "on" "off" } {
218         run_condition_test "exactly one thread is hit" \
219             1 "is_matching_tid (arg, 1)" \
220             $target_async $target_non_stop
221         run_condition_test "exactly two threads are hit" \
222             2 "(is_matching_tid (arg, 0) || is_matching_tid (arg, 2))" \
223             $target_async $target_non_stop
224         run_condition_test "all three threads are hit" \
225             3 "return_true ()" \
226             $target_async $target_non_stop
227         run_condition_test "no thread is hit" \
228             0 "return_false ()" \
229             $target_async $target_non_stop
231         run_kill_and_restart_test $target_async $target_non_stop
232         run_bp_cond_segfaults $target_async $target_non_stop
233         run_bp_cond_hits_breakpoint $target_async $target_non_stop
234     }