pending-bp.exp revision 1.1 1 1.1 christos # Copyright 2023-2024 Free Software Foundation, Inc.
2 1.1 christos
3 1.1 christos # This program is free software; you can redistribute it and/or modify
4 1.1 christos # it under the terms of the GNU General Public License as published by
5 1.1 christos # the Free Software Foundation; either version 3 of the License, or
6 1.1 christos # (at your option) any later version.
7 1.1 christos #
8 1.1 christos # This program is distributed in the hope that it will be useful,
9 1.1 christos # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 1.1 christos # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 1.1 christos # GNU General Public License for more details.
12 1.1 christos #
13 1.1 christos # You should have received a copy of the GNU General Public License
14 1.1 christos # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 1.1 christos
16 1.1 christos # Tests related to pending breakpoints in a multi-inferior environment.
17 1.1 christos
18 1.1 christos require allow_shlib_tests !use_gdb_stub
19 1.1 christos
20 1.1 christos standard_testfile
21 1.1 christos
22 1.1 christos set libname $testfile-lib
23 1.1 christos set srcfile_lib $srcdir/$subdir/$libname.c
24 1.1 christos set binfile_lib [standard_output_file $libname.so]
25 1.1 christos
26 1.1 christos if { [gdb_compile_shlib $srcfile_lib $binfile_lib {}] != "" } {
27 1.1 christos untested "failed to compile shared library 1"
28 1.1 christos return -1
29 1.1 christos }
30 1.1 christos
31 1.1 christos set binfile_lib_target [gdb_download_shlib $binfile_lib]
32 1.1 christos
33 1.1 christos if { [build_executable "failed to prepare" $testfile $srcfile \
34 1.1 christos [list debug \
35 1.1 christos additional_flags=-DSHLIB_NAME=\"$binfile_lib_target\" \
36 1.1 christos shlib_load]] } {
37 1.1 christos return -1
38 1.1 christos }
39 1.1 christos
40 1.1 christos # Start two inferiors, both running the same test binary. The arguments
41 1.1 christos # INF_1_STOP and INF_2_STOP are source code patterns that are passed to
42 1.1 christos # gdb_get_line_number to figure out where each inferior should be stopped.
43 1.1 christos #
44 1.1 christos # This proc does a clean_restart and leaves inferior 2 selected. Also the
45 1.1 christos # 'breakpoint pending' flag is enabled, so pending breakpoints can be created
46 1.1 christos # without GDB prompting the user.
47 1.1 christos proc do_test_setup { inf_1_stop inf_2_stop } {
48 1.1 christos clean_restart ${::binfile}
49 1.1 christos
50 1.1 christos gdb_locate_shlib $::binfile_lib
51 1.1 christos
52 1.1 christos if {![runto_main]} {
53 1.1 christos return false
54 1.1 christos }
55 1.1 christos
56 1.1 christos gdb_breakpoint [gdb_get_line_number ${inf_1_stop}] temporary
57 1.1 christos gdb_continue_to_breakpoint "move inferior 1 into position"
58 1.1 christos
59 1.1 christos gdb_test "add-inferior -exec ${::binfile}" \
60 1.1 christos "Added inferior 2.*" "add inferior 2"
61 1.1 christos gdb_test "inferior 2" "Switching to inferior 2 .*" "switch to inferior 2"
62 1.1 christos
63 1.1 christos if {![runto_main]} {
64 1.1 christos return false
65 1.1 christos }
66 1.1 christos
67 1.1 christos gdb_breakpoint [gdb_get_line_number ${inf_2_stop}] temporary
68 1.1 christos gdb_continue_to_breakpoint "move inferior 2 into position"
69 1.1 christos
70 1.1 christos gdb_test_no_output "set breakpoint pending on"
71 1.1 christos
72 1.1 christos return true
73 1.1 christos }
74 1.1 christos
75 1.1 christos # Create a breakpoint on the function 'foo' in THREAD. It is expected
76 1.1 christos # that the breakpoint created will be pending, this is checked by
77 1.1 christos # running the 'info breakpoints' command.
78 1.1 christos #
79 1.1 christos # Returns the number for the newly created breakpoint.
80 1.1 christos proc do_create_pending_foo_breakpoint { {thread "1.1"} } {
81 1.1 christos gdb_test "break foo thread $thread" \
82 1.1 christos [multi_line \
83 1.1 christos "Function \"foo\" not defined\\." \
84 1.1 christos "Breakpoint $::decimal \\(foo\\) pending\."] \
85 1.1 christos "set pending thread-specific breakpoint"
86 1.1 christos set bpnum [get_integer_valueof "\$bpnum" "*INVALID*" \
87 1.1 christos "get number for thread-specific breakpoint on foo"]
88 1.1 christos gdb_test "info breakpoints $bpnum" \
89 1.1 christos [multi_line \
90 1.1 christos "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+foo" \
91 1.1 christos "\\s+stop only in thread [string_to_regexp $thread]"] \
92 1.1 christos "check thread-specific breakpoint is initially pending"
93 1.1 christos
94 1.1 christos return $bpnum
95 1.1 christos }
96 1.1 christos
97 1.1 christos # Create a breakpoint on the function 'foo' in THREAD. It is expected
98 1.1 christos # that the breakpoint created will not be pending, this is checked by
99 1.1 christos # running the 'info breakpoints' command.
100 1.1 christos #
101 1.1 christos # Returns the number for the newly created breakpoint.
102 1.1 christos proc do_create_foo_breakpoint { {thread "1.1"} } {
103 1.1 christos gdb_test "break foo thread $thread" \
104 1.1 christos "Breakpoint $::decimal at $::hex" \
105 1.1 christos "set thread-specific breakpoint"
106 1.1 christos set bpnum [get_integer_valueof "\$bpnum" "*INVALID*" \
107 1.1 christos "get number for thread-specific breakpoint on foo"]
108 1.1 christos gdb_test "info breakpoints $bpnum" \
109 1.1 christos [multi_line \
110 1.1 christos "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$::hex\\s+<foo\[^>\]*> inf $::decimal" \
111 1.1 christos "\\s+stop only in thread [string_to_regexp $thread]"] \
112 1.1 christos "check thread-specific breakpoint is initially pending"
113 1.1 christos
114 1.1 christos return $bpnum
115 1.1 christos }
116 1.1 christos
117 1.1 christos # Check that when a breakpoint is in the pending state, but that breakpoint
118 1.1 christos # does have some locations (those locations themselves are pending), GDB
119 1.1 christos # doesn't display the inferior list in the 'info breakpoints' output.
120 1.1 christos proc_with_prefix test_no_inf_display {} {
121 1.1 christos do_test_setup "Break before open" "Break before open"
122 1.1 christos
123 1.1 christos # Create a breakpoint on 'foo'. As the shared library (that
124 1.1 christos # contains foo) has not been loaded into any inferior yet, then
125 1.1 christos # there will be no locations and the breakpoint will be created
126 1.1 christos # pending. Pass the 'allow-pending' flag so the gdb_breakpoint
127 1.1 christos # correctly expects the new breakpoint to be pending.
128 1.1 christos gdb_breakpoint "foo" allow-pending
129 1.1 christos set bpnum [get_integer_valueof "\$bpnum" "*INVALID*" \
130 1.1 christos "get foo breakpoint number"]
131 1.1 christos
132 1.1 christos # Check the 'info breakpoints' output; the breakpoint is pending with
133 1.1 christos # no 'inf X' appearing at the end of the line.
134 1.1 christos gdb_test "info breakpoint $bpnum" \
135 1.1 christos "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+foo" \
136 1.1 christos "check info bp before locations have been created"
137 1.1 christos
138 1.1 christos # Now select inferior 1 and allow the inferior to run forward to the
139 1.1 christos # point where a breakpoint location for foo will have been created.
140 1.1 christos gdb_test "inferior 1" "Switching to inferior 1 .*"
141 1.1 christos gdb_breakpoint [gdb_get_line_number "Break after open"] temporary
142 1.1 christos gdb_continue_to_breakpoint \
143 1.1 christos "move inferior 1 until a location has been added"
144 1.1 christos
145 1.1 christos # Check the 'info breakpoints' output. Notice we display the inferior
146 1.1 christos # list at the end of the breakpoint line.
147 1.1 christos gdb_test "info breakpoint $bpnum" \
148 1.1 christos "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$::hex\\s+<foo\[^>\]*>\\s+inf 1" \
149 1.1 christos "check info breakpoints while breakpoint is inserted"
150 1.1 christos
151 1.1 christos # Continue inferior 1 until the shared library has been unloaded. The
152 1.1 christos # breakpoint on 'foo' will return to the pending state. We will need to
153 1.1 christos # 'continue' twice as the first time will hit the 'foo' breakpoint.
154 1.1 christos gdb_breakpoint [gdb_get_line_number "Break after close"] temporary
155 1.1 christos gdb_continue_to_breakpoint "hit the breakpoint in foo"
156 1.1 christos gdb_continue_to_breakpoint "after close library"
157 1.1 christos
158 1.1 christos # Check the 'info breakpoints' output, check there is no 'inf 1' at the
159 1.1 christos # end of the breakpoint line.
160 1.1 christos gdb_test "info breakpoint $bpnum" \
161 1.1 christos [multi_line \
162 1.1 christos "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+foo" \
163 1.1 christos "\\s+breakpoint already hit 1 time"] \
164 1.1 christos "check info breakpoints while breakpoint is pending"
165 1.1 christos }
166 1.1 christos
167 1.1 christos # Setup two inferiors. In #1 the symbol 'foo' has not yet been
168 1.1 christos # loaded, while in #2 the symbol 'foo' has been loaded.
169 1.1 christos #
170 1.1 christos # Create a thread-specific breakpoint on 'foo' tied to a thread in
171 1.1 christos # inferior #1, the breakpoint should be pending -- 'foo' is not yet
172 1.1 christos # loaded in #1.
173 1.1 christos #
174 1.1 christos # Now move inferior #1 forward until 'foo' is loaded, check the
175 1.1 christos # breakpoint is no longer pending.
176 1.1 christos #
177 1.1 christos # Move inferior #1 forward more until 'foo' is unloaded, check that
178 1.1 christos # the breakpoint returns to the pending state.
179 1.1 christos proc_with_prefix test_pending_toggle { } {
180 1.1 christos
181 1.1 christos do_test_setup "Break before open" "Break before close"
182 1.1 christos
183 1.1 christos set bpnum [do_create_pending_foo_breakpoint]
184 1.1 christos
185 1.1 christos # Now return to inferior 1 and continue until the shared library is
186 1.1 christos # loaded, the breakpoint should become non-pending.
187 1.1 christos gdb_test "inferior 1" "Switching to inferior 1 .*" \
188 1.1 christos "switch back to inferior 1"
189 1.1 christos gdb_continue_to_breakpoint "stop in foo in inferior 1" "foo \\(\\) .*"
190 1.1 christos
191 1.1 christos gdb_test "info breakpoint $bpnum" \
192 1.1 christos [multi_line \
193 1.1 christos "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$::hex <foo\[^>\]*> inf 1" \
194 1.1 christos "\\s+stop only in thread 1\\.1" \
195 1.1 christos "\\s+breakpoint already hit 1 time"] \
196 1.1 christos "check thread-specific breakpoint is no longer pending"
197 1.1 christos
198 1.1 christos gdb_breakpoint [gdb_get_line_number "Break after close"] temporary
199 1.1 christos gdb_continue_to_breakpoint "close library"
200 1.1 christos gdb_test "info breakpoints $bpnum" \
201 1.1 christos [multi_line \
202 1.1 christos "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+foo" \
203 1.1 christos "\\s+stop only in thread 1\\.1" \
204 1.1 christos "\\s+breakpoint already hit 1 time"] \
205 1.1 christos "check thread-specific breakpoint is pending again"
206 1.1 christos }
207 1.1 christos
208 1.1 christos # Create a Python variable VAR and set it to the gdb.Breakpoint object
209 1.1 christos # corresponding to the breakpoint numbered BPNUM. If THREAD is not
210 1.1 christos # the empty string then THREAD should be an integer, check that
211 1.1 christos # gdb.Breakpoint.thread is set to the value of THREAD. Otherwise, if
212 1.1 christos # THREAD is the empty string, check that gdb.Breakpoint.thread is set
213 1.1 christos # to None.
214 1.1 christos proc py_find_breakpoint { var bpnum {thread ""} } {
215 1.1 christos gdb_test_no_output \
216 1.1 christos "python ${var}=\[b for b in gdb.breakpoints() if b.number == $bpnum\]\[0\]" \
217 1.1 christos "find Python gdb.Breakpoint object"
218 1.1 christos if { $thread ne "" } {
219 1.1 christos gdb_test_no_output "python assert(${var}.thread == ${thread})" \
220 1.1 christos "check thread attribute is currently correct"
221 1.1 christos } else {
222 1.1 christos gdb_test_no_output "python assert(${var}.thread is None)" \
223 1.1 christos "check thread attribute is currently correct"
224 1.1 christos }
225 1.1 christos }
226 1.1 christos
227 1.1 christos # Setup two inferiors. In #1 the symbol 'foo' has not yet been
228 1.1 christos # loaded, while in #2 the symbol 'foo' has been loaded.
229 1.1 christos #
230 1.1 christos # Create a thread-specific breakpoint on 'foo' tied to a thread in
231 1.1 christos # inferior #1, the breakpoint should be pending -- 'foo' is not yet
232 1.1 christos # loaded in #1.
233 1.1 christos #
234 1.1 christos # Use Python to change the thread of the thread-specific breakpoint to
235 1.1 christos # a thread in inferior #2, at this point the thread should gain a
236 1.1 christos # location and become non-pending.
237 1.1 christos #
238 1.1 christos # Set the thread back to a thread in inferior #1, the breakpoint
239 1.1 christos # should return to the pending state.
240 1.1 christos proc_with_prefix py_test_toggle_thread {} {
241 1.1 christos do_test_setup "Break before open" "Break after open"
242 1.1 christos
243 1.1 christos set bpnum [do_create_pending_foo_breakpoint]
244 1.1 christos
245 1.1 christos py_find_breakpoint "bp" $bpnum 1
246 1.1 christos
247 1.1 christos gdb_test_no_output "python bp.thread = 2" \
248 1.1 christos "change thread on thread-specific breakpoint"
249 1.1 christos gdb_test "info breakpoint $bpnum" \
250 1.1 christos [multi_line \
251 1.1 christos "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+$::hex <foo\[^>\]*> inf 2" \
252 1.1 christos "\\s+stop only in thread 2\\.1"] \
253 1.1 christos "check thread-specific breakpoint now has a location"
254 1.1 christos
255 1.1 christos gdb_test_no_output "set call_count = 2" "set call_count in inferior 2"
256 1.1 christos gdb_continue_to_breakpoint "stop at foo in inferior 2" "foo \\(\\) .*"
257 1.1 christos
258 1.1 christos gdb_test_no_output "python bp.thread = 1" \
259 1.1 christos "restore thread on thread-specific breakpoint"
260 1.1 christos gdb_test "info breakpoints $bpnum" \
261 1.1 christos [multi_line \
262 1.1 christos "$bpnum\\s+breakpoint\\s+keep\\s+y\\s+<PENDING>\\s+foo" \
263 1.1 christos "\\s+stop only in thread 1\\.1" \
264 1.1 christos "\\s+breakpoint already hit 1 time"] \
265 1.1 christos "check thread-specific breakpoint has returned to pending"
266 1.1 christos
267 1.1 christos gdb_breakpoint [gdb_get_line_number "Break after close"] temporary
268 1.1 christos gdb_continue_to_breakpoint "stop after close in inferior 2" \
269 1.1 christos ".* Break after close\\. .*"
270 1.1 christos
271 1.1 christos gdb_test "inferior 1" "Switching to inferior 1 .*" \
272 1.1 christos "switch to inferior 1"
273 1.1 christos gdb_continue_to_breakpoint "stop at foo in inferior 1" "foo \\(\\) .*"
274 1.1 christos }
275 1.1 christos
276 1.1 christos # Setup two inferiors. Both inferiors have the symbol 'foo'
277 1.1 christos # available.
278 1.1 christos #
279 1.1 christos # Create a thread-specific breakpoint on 'foo' tied to a thread in
280 1.1 christos # inferior #1, the breakpoint should not be pending, but will only
281 1.1 christos # have a single location, the location in inferior #1.
282 1.1 christos #
283 1.1 christos # Use Python to change the thread of the thread-specific breakpoint to
284 1.1 christos # None. At this point the breakpoint should gain a second location, a
285 1.1 christos # location in inferior #2.
286 1.1 christos proc_with_prefix py_test_clear_thread {} {
287 1.1 christos do_test_setup "Break after open" "Break after open"
288 1.1 christos
289 1.1 christos set bpnum [do_create_foo_breakpoint]
290 1.1 christos
291 1.1 christos py_find_breakpoint "bp" $bpnum 1
292 1.1 christos
293 1.1 christos gdb_test_no_output "python bp.thread = None" \
294 1.1 christos "clear thread on thread-specific breakpoint"
295 1.1 christos gdb_test "info breakpoints $bpnum" \
296 1.1 christos [multi_line \
297 1.1 christos "${bpnum}\\s+breakpoint\\s+keep y\\s+<MULTIPLE>\\s*" \
298 1.1 christos "${bpnum}\\.1\\s+y\\s+${::hex}\\s+<foo\[^>\]*> inf $::decimal" \
299 1.1 christos "${bpnum}\\.2\\s+y\\s+${::hex}\\s+<foo\[^>\]*> inf $::decimal"] \
300 1.1 christos "check for a location in both inferiors"
301 1.1 christos
302 1.1 christos gdb_continue_to_breakpoint "stop at foo in inferior 2" "foo \\(\\) .*"
303 1.1 christos gdb_test_no_output "set call_count = 2" "set call_count in inferior 2"
304 1.1 christos
305 1.1 christos gdb_test "inferior 1" "Switching to inferior 1 .*" \
306 1.1 christos "switch to inferior 1"
307 1.1 christos gdb_continue_to_breakpoint "stop at foo in inferior 1" "foo \\(\\) .*"
308 1.1 christos gdb_test_no_output "set call_count = 2" "set call_count in inferior 1"
309 1.1 christos
310 1.1 christos gdb_test_no_output "python bp.thread = 2"
311 1.1 christos gdb_test "info breakpoints $bpnum" \
312 1.1 christos [multi_line \
313 1.1 christos "${bpnum}\\s+breakpoint\\s+keep y\\s+${::hex}\\s+<foo\[^>\]*> inf 2" \
314 1.1 christos "\\s+stop only in thread 2\\.1" \
315 1.1 christos "\\s+breakpoint already hit 2 times"] \
316 1.1 christos "check for a location only in inferior 2"
317 1.1 christos
318 1.1 christos gdb_breakpoint [gdb_get_line_number "Break after close"] temporary
319 1.1 christos gdb_continue_to_breakpoint "stop after close in inferior 1" \
320 1.1 christos ".* Break after close\\. .*"
321 1.1 christos
322 1.1 christos gdb_test "inferior 2" "Switching to inferior 2 .*" \
323 1.1 christos "switch back to inferior 2"
324 1.1 christos gdb_continue_to_breakpoint "stop at foo again in inferior 2" \
325 1.1 christos "foo \\(\\) .*"
326 1.1 christos }
327 1.1 christos
328 1.1 christos # Run all the tests.
329 1.1 christos test_no_inf_display
330 1.1 christos test_pending_toggle
331 1.1 christos py_test_toggle_thread
332 1.1 christos py_test_clear_thread
333