]>
Commit | Line | Data |
---|---|---|
4a94e368 | 1 | # Copyright 2020-2022 Free Software Foundation, Inc. |
b5fa468f TBA |
2 | |
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. | |
7 | # | |
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. | |
12 | # | |
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/>. | |
15 | ||
16 | # Test defining a conditional breakpoint that applies to multiple | |
17 | # locations with different contexts (e.g. different set of local vars). | |
18 | ||
19 | standard_testfile .cc | |
20 | ||
21 | if {[prepare_for_testing "failed to prepare" ${binfile} ${srcfile}]} { | |
22 | return | |
23 | } | |
24 | ||
25 | set warning "warning: failed to validate condition" | |
26 | set fill "\[^\r\n\]*" | |
27 | ||
50757f95 TBA |
28 | # Location indices are determined by their address, which depends on |
29 | # how the compiler emits the code. We keep a map from the location | |
30 | # index to the location context (i.e. A, Base, or C), so that we can | |
31 | # write tests without hard-coding location indices. | |
32 | set loc_name(1) "" | |
33 | set loc_name(2) "" | |
34 | set loc_name(3) "" | |
35 | # And, for convenience, a reverse map from the name to the index. | |
36 | set loc_index(A) 0 | |
37 | set loc_index(Base) 0 | |
38 | set loc_index(C) 0 | |
39 | ||
40 | # Find breakpoint location contexts. | |
41 | ||
42 | proc find_location_contexts {} { | |
43 | global loc_name loc_index bpnum1 fill | |
44 | global decimal hex gdb_prompt | |
45 | ||
46 | gdb_test_multiple "info breakpoint $bpnum1" "find_location_indices" { | |
47 | -re "stop only if ${fill}\r\n" { | |
48 | exp_continue | |
49 | } | |
50 | -re "^${bpnum1}\.($decimal) ${fill} ${hex} in (A|Base|C)::func${fill}\r\n" { | |
51 | set index $expect_out(1,string) | |
52 | set name $expect_out(2,string) | |
53 | set loc_name($index) $name | |
54 | set loc_index($name) $index | |
55 | exp_continue | |
56 | } | |
57 | -re "$gdb_prompt $" { | |
58 | verbose -log "Loc names: $loc_name(1), $loc_name(2), $loc_name(3)" | |
59 | gdb_assert { ![string equal $loc_name(1) $loc_name(2)] } | |
60 | gdb_assert { ![string equal $loc_name(1) $loc_name(3)] } | |
61 | gdb_assert { ![string equal $loc_name(2) $loc_name(3)] } | |
62 | gdb_assert { [string length $loc_name(1)] > 0 } | |
63 | gdb_assert { [string length $loc_name(2)] > 0 } | |
64 | gdb_assert { [string length $loc_name(3)] > 0 } | |
65 | } | |
66 | } | |
67 | } | |
b5fa468f | 68 | |
50757f95 TBA |
69 | # Test the breakpoint location enabled states. STATES is a list of |
70 | # location states. We assume STATES to contain the state for A, Base, | |
71 | # and C, and in this order. E.g. {N* y n} for 'N*' at A::func, 'y' at | |
72 | # B::func, and 'n' at C::func, respectively. | |
b5fa468f | 73 | |
50757f95 TBA |
74 | proc check_bp_locations {bpnum states cond {msg ""}} { |
75 | global loc_name fill | |
b5fa468f | 76 | |
50757f95 TBA |
77 | # Map location names to location states. |
78 | set loc_states(A) [lindex $states 0] | |
79 | set loc_states(Base) [lindex $states 1] | |
80 | set loc_states(C) [lindex $states 2] | |
81 | ||
82 | if {$cond == ""} { | |
83 | set cond_info "" | |
84 | } else { | |
85 | set bp_hit_info "${fill}(\r\n${fill}breakpoint already hit 1 time)?" | |
86 | set cond_info "\r\n${fill}stop only if ${cond}${bp_hit_info}" | |
87 | } | |
88 | ||
89 | set expected [multi_line \ | |
90 | "Num${fill}" \ | |
91 | "${bpnum}${fill}breakpoint${fill}keep y${fill}MULTIPLE${fill}${cond_info}" \ | |
92 | "${bpnum}.1${fill} $loc_states($loc_name(1)) ${fill}" \ | |
93 | "${bpnum}.2${fill} $loc_states($loc_name(2)) ${fill}" \ | |
94 | "${bpnum}.3${fill} $loc_states($loc_name(3)) ${fill}"] | |
95 | ||
96 | if {[lsearch $states N*] >= 0} { | |
97 | append expected "\r\n\\(\\*\\): Breakpoint condition is invalid at this location." | |
98 | } | |
99 | ||
100 | gdb_test "info break $bpnum" $expected "check bp $bpnum $msg" | |
b5fa468f TBA |
101 | } |
102 | ||
103 | # Scenario 1: Define breakpoints conditionally, using the "break N if | |
104 | # cond" syntax. Run the program, check that we hit those locations | |
105 | # only. | |
106 | ||
107 | with_test_prefix "scenario 1" { | |
50757f95 TBA |
108 | # Define the conditional breakpoints. Two locations (Base::func |
109 | # and C::func) should be disabled. We do not test location | |
110 | # indices strictly at this moment, because we don't know them, | |
111 | # yet. We have strict location index tests below. | |
b5fa468f TBA |
112 | gdb_test "break func if a == 10" \ |
113 | [multi_line \ | |
50757f95 | 114 | "${warning} at location $decimal, disabling:" \ |
b5fa468f | 115 | " No symbol \"a\" in current context." \ |
50757f95 | 116 | "${warning} at location $decimal, disabling:" \ |
b5fa468f TBA |
117 | " No symbol \"a\" in current context." \ |
118 | "Breakpoint $decimal at $fill .3 locations."] \ | |
119 | "define bp with condition a == 10" | |
120 | set bpnum1 [get_integer_valueof "\$bpnum" 0 "get bpnum1"] | |
121 | ||
122 | gdb_test "break func if c == 30" \ | |
123 | [multi_line \ | |
50757f95 | 124 | ".*${warning} at location $decimal, disabling:" \ |
b5fa468f | 125 | " No symbol \"c\" in current context." \ |
50757f95 | 126 | ".*${warning} at location $decimal, disabling:" \ |
b5fa468f TBA |
127 | " No symbol \"c\" in current context." \ |
128 | ".*Breakpoint $decimal at $fill .3 locations."] \ | |
129 | "define bp with condition c == 30" | |
130 | set bpnum2 [get_integer_valueof "\$bpnum" 0 "get bpnum2"] | |
131 | ||
50757f95 TBA |
132 | find_location_contexts |
133 | ||
134 | with_test_prefix "before run" { | |
135 | check_bp_locations $bpnum1 {y N* N*} "a == 10" | |
136 | check_bp_locations $bpnum2 {N* N* y} "c == 30" | |
137 | } | |
b5fa468f TBA |
138 | |
139 | # Do not use runto_main, it deletes all breakpoints. | |
140 | gdb_run_cmd | |
141 | ||
142 | # Check our conditional breakpoints. | |
78805ff8 | 143 | gdb_test "" ".*Breakpoint $bkptno_num_re, A::func .*" \ |
b5fa468f TBA |
144 | "run until A::func" |
145 | gdb_test "print a" " = 10" | |
146 | ||
78805ff8 | 147 | gdb_test "continue" "Continuing.*Breakpoint $bkptno_num_re, C::func .*" \ |
b5fa468f TBA |
148 | "run until C::func" |
149 | gdb_test "print c" " = 30" | |
150 | ||
151 | # No more hits! | |
152 | gdb_continue_to_end | |
153 | ||
50757f95 TBA |
154 | with_test_prefix "after run" { |
155 | check_bp_locations $bpnum1 {y N* N*} "a == 10" | |
156 | check_bp_locations $bpnum2 {N* N* y} "c == 30" | |
157 | } | |
b5fa468f TBA |
158 | } |
159 | ||
160 | # Start GDB with two breakpoints and define the conditions separately. | |
161 | ||
162 | proc setup_bps {} { | |
50757f95 TBA |
163 | global srcfile binfile srcfile2 decimal |
164 | global bpnum1 bpnum2 bp_location warning loc_index | |
b5fa468f TBA |
165 | |
166 | clean_restart ${binfile} | |
167 | ||
168 | # Define the breakpoints. | |
169 | gdb_breakpoint "func" | |
170 | set bpnum1 [get_integer_valueof "\$bpnum" 0 "get bpnum1"] | |
171 | ||
172 | gdb_breakpoint "func" | |
173 | set bpnum2 [get_integer_valueof "\$bpnum" 0 "get bpnum2"] | |
174 | ||
175 | # Defining a condition on 'a' disables 2 locations. | |
50757f95 | 176 | set locs [lsort -integer "$loc_index(Base) $loc_index(C)"] |
b5fa468f TBA |
177 | gdb_test "cond $bpnum1 a == 10" \ |
178 | [multi_line \ | |
50757f95 | 179 | "$warning at location ${bpnum1}.[lindex $locs 0], disabling:" \ |
b5fa468f | 180 | " No symbol \"a\" in current context." \ |
50757f95 | 181 | "$warning at location ${bpnum1}.[lindex $locs 1], disabling:" \ |
b5fa468f TBA |
182 | " No symbol \"a\" in current context."] |
183 | ||
184 | # Defining a condition on 'c' disables 2 locations. | |
50757f95 | 185 | set locs [lsort -integer "$loc_index(Base) $loc_index(A)"] |
b5fa468f TBA |
186 | gdb_test "cond $bpnum2 c == 30" \ |
187 | [multi_line \ | |
50757f95 | 188 | "$warning at location ${bpnum2}.[lindex $locs 0], disabling:" \ |
b5fa468f | 189 | " No symbol \"c\" in current context." \ |
50757f95 | 190 | "$warning at location ${bpnum2}.[lindex $locs 1], disabling:" \ |
b5fa468f TBA |
191 | " No symbol \"c\" in current context."] |
192 | } | |
193 | ||
194 | # Scenario 2: Define breakpoints unconditionally, and then define | |
195 | # conditions using the "cond N <cond>" syntax. Expect that the | |
196 | # locations where <cond> is not evaluatable are disabled. Run the | |
197 | # program, check that we hit the enabled locations only. | |
198 | ||
199 | with_test_prefix "scenario 2" { | |
200 | setup_bps | |
201 | ||
50757f95 TBA |
202 | with_test_prefix "before run" { |
203 | check_bp_locations $bpnum1 {y N* N*} "a == 10" | |
204 | check_bp_locations $bpnum2 {N* N* y} "c == 30" | |
205 | } | |
b5fa468f TBA |
206 | |
207 | # Do not use runto_main, it deletes all breakpoints. | |
208 | gdb_run_cmd | |
209 | ||
210 | # Check that we hit enabled locations only. | |
78805ff8 | 211 | gdb_test "" ".*Breakpoint $bkptno_num_re, A::func .*" \ |
b5fa468f TBA |
212 | "run until A::func" |
213 | gdb_test "print a" " = 10" | |
214 | ||
78805ff8 | 215 | gdb_test "continue" "Continuing.*Breakpoint $bkptno_num_re, C::func .*" \ |
b5fa468f TBA |
216 | "run until C::func" |
217 | gdb_test "print c" " = 30" | |
218 | ||
219 | # No more hits! | |
220 | gdb_continue_to_end | |
221 | ||
50757f95 TBA |
222 | with_test_prefix "after run" { |
223 | check_bp_locations $bpnum1 {y N* N*} "a == 10" | |
224 | check_bp_locations $bpnum2 {N* N* y} "c == 30" | |
b5fa468f | 225 | } |
b5fa468f TBA |
226 | } |
227 | ||
228 | # Scenario 3: Apply misc. checks on the already-defined breakpoints. | |
229 | ||
230 | with_test_prefix "scenario 3" { | |
231 | setup_bps | |
232 | ||
50757f95 | 233 | set locs [lsort -integer "$loc_index(Base) $loc_index(A)"] |
b5fa468f TBA |
234 | gdb_test "cond $bpnum1 c == 30" \ |
235 | [multi_line \ | |
50757f95 | 236 | "${warning} at location ${bpnum1}.[lindex $locs 0], disabling:" \ |
b5fa468f | 237 | " No symbol \"c\" in current context." \ |
50757f95 | 238 | "${warning} at location ${bpnum1}.[lindex $locs 1], disabling:" \ |
b5fa468f | 239 | " No symbol \"c\" in current context." \ |
50757f95 | 240 | "Breakpoint ${bpnum1}'s condition is now valid at location $loc_index(C), enabling."] \ |
b5fa468f | 241 | "change the condition of bp 1" |
50757f95 | 242 | check_bp_locations $bpnum1 {N* N* y} "c == 30" "after changing the condition" |
b5fa468f TBA |
243 | |
244 | gdb_test "cond $bpnum1" \ | |
245 | [multi_line \ | |
50757f95 TBA |
246 | "Breakpoint ${bpnum1}'s condition is now valid at location [lindex $locs 0], enabling." \ |
247 | "Breakpoint ${bpnum1}'s condition is now valid at location [lindex $locs 1], enabling." \ | |
b5fa468f TBA |
248 | "Breakpoint ${bpnum1} now unconditional."] \ |
249 | "reset the condition of bp 1" | |
50757f95 | 250 | check_bp_locations $bpnum1 {y y y} "" "after resetting the condition" |
b5fa468f | 251 | |
50757f95 TBA |
252 | gdb_test_no_output "disable ${bpnum2}.$loc_index(A)" |
253 | check_bp_locations $bpnum2 {N* N* y} "c == 30" "after disabling loc for A" | |
b5fa468f TBA |
254 | |
255 | gdb_test "cond $bpnum2" ".*" "reset the condition of bp 2" | |
50757f95 | 256 | check_bp_locations $bpnum2 {n y y} "" "loc for A should remain disabled" |
b5fa468f | 257 | |
50757f95 TBA |
258 | gdb_test_no_output "disable ${bpnum2}.$loc_index(C)" |
259 | check_bp_locations $bpnum2 {n y n} "" "after disabling loc for C" | |
b5fa468f TBA |
260 | |
261 | gdb_test "cond $bpnum2 c == 30" \ | |
262 | [multi_line \ | |
50757f95 | 263 | "${warning} at location ${bpnum2}.$loc_index(Base), disabling:" \ |
b5fa468f TBA |
264 | " No symbol \"c\" in current context."] \ |
265 | "re-define a condition" | |
50757f95 | 266 | check_bp_locations $bpnum2 {N* N* n} "c == 30" "loc for C should remain disabled" |
b5fa468f | 267 | |
50757f95 TBA |
268 | gdb_test "enable ${bpnum2}.$loc_index(Base)" \ |
269 | "Breakpoint ${bpnum2}'s condition is invalid at location $loc_index(Base), cannot enable." \ | |
b5fa468f | 270 | "reject enabling a location that is disabled-by-cond" |
50757f95 | 271 | check_bp_locations $bpnum2 {N* N* n} "c == 30" "after enable attempt" |
b5fa468f TBA |
272 | |
273 | gdb_test "cond $bpnum2 garbage" \ | |
274 | "No symbol \"garbage\" in current context." \ | |
275 | "reject condition if bad for all locations" | |
276 | ||
277 | gdb_test_no_output "delete $bpnum1" | |
278 | ||
279 | # Do not use runto_main, it deletes all breakpoints. | |
280 | gdb_breakpoint "main" | |
281 | gdb_run_cmd | |
282 | gdb_test "" ".*reakpoint .*, main .*${srcfile}.*" "start" | |
283 | ||
284 | # The second BP's locations are all disabled. No more hits! | |
285 | gdb_continue_to_end | |
286 | } | |
733d554a TBA |
287 | |
288 | # Scenario 4: Test the '-force'/'-force-condition' flag. | |
289 | ||
290 | with_test_prefix "force" { | |
291 | clean_restart ${binfile} | |
292 | ||
293 | gdb_breakpoint "func" | |
294 | # Pick a condition that is invalid at every location. | |
295 | set bpnum1 [get_integer_valueof "\$bpnum" 0 "get bpnum1"] | |
296 | gdb_test "cond -force $bpnum1 foo" \ | |
297 | [multi_line \ | |
298 | "${warning} at location ${bpnum1}.1, disabling:" \ | |
299 | " No symbol \"foo\" in current context." \ | |
300 | "${warning} at location ${bpnum1}.2, disabling:" \ | |
301 | " No symbol \"foo\" in current context." \ | |
302 | "${warning} at location ${bpnum1}.3, disabling:" \ | |
303 | " No symbol \"foo\" in current context."] \ | |
304 | "force the condition of bp 1" | |
50757f95 | 305 | check_bp_locations $bpnum1 {N* N* N*} "foo" "after forcing the condition" |
733d554a TBA |
306 | |
307 | # Now with the 'break' command. | |
308 | gdb_breakpoint "func -force-condition if baz" | |
309 | set bpnum2 [get_integer_valueof "\$bpnum" 0 "get bpnum2"] | |
50757f95 | 310 | check_bp_locations $bpnum2 {N* N* N*} "baz" "set using the break command" |
733d554a | 311 | } |