Commit | Line | Data |
---|---|---|
b5fa468f TBA |
1 | # Copyright 2020 Free Software Foundation, Inc. |
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 | ||
28 | # Check that breakpoints are as expected. | |
29 | ||
30 | proc test_info_break {suffix} { | |
31 | global bpnum1 bpnum2 fill | |
32 | ||
33 | set bp_hit_info "${fill}(\r\n${fill}breakpoint already hit 1 time)?" | |
34 | ||
35 | gdb_test "info break ${bpnum1} ${bpnum2}" \ | |
36 | [multi_line \ | |
37 | "Num${fill}" \ | |
38 | "${bpnum1}${fill}breakpoint${fill}keep y${fill}MULTIPLE${fill}" \ | |
39 | "${fill}stop only if a == 10${bp_hit_info}" \ | |
40 | "${bpnum1}.1${fill}N\\*${fill}Base::func${fill}" \ | |
41 | "${bpnum1}.2${fill}y${fill}A::func${fill}" \ | |
42 | "${bpnum1}.3${fill}N\\*${fill}C::func${fill}" \ | |
43 | "${bpnum2}${fill}breakpoint${fill}keep y${fill}MULTIPLE${fill}" \ | |
44 | "${fill}stop only if c == 30${bp_hit_info}" \ | |
45 | "${bpnum2}.1${fill}N\\*${fill}Base::func${fill}" \ | |
46 | "${bpnum2}.2${fill}N\\*${fill}A::func${fill}" \ | |
47 | "${bpnum2}.3${fill}y${fill}C::func${fill}" \ | |
48 | "\\(\\*\\): Breakpoint condition is invalid at this location."] \ | |
49 | "info break $suffix" | |
50 | } | |
51 | ||
52 | # Scenario 1: Define breakpoints conditionally, using the "break N if | |
53 | # cond" syntax. Run the program, check that we hit those locations | |
54 | # only. | |
55 | ||
56 | with_test_prefix "scenario 1" { | |
57 | # Define the conditional breakpoints. | |
58 | gdb_test "break func if a == 10" \ | |
59 | [multi_line \ | |
60 | "${warning} at location 1, disabling:" \ | |
61 | " No symbol \"a\" in current context." \ | |
62 | "${warning} at location 3, disabling:" \ | |
63 | " No symbol \"a\" in current context." \ | |
64 | "Breakpoint $decimal at $fill .3 locations."] \ | |
65 | "define bp with condition a == 10" | |
66 | set bpnum1 [get_integer_valueof "\$bpnum" 0 "get bpnum1"] | |
67 | ||
68 | gdb_test "break func if c == 30" \ | |
69 | [multi_line \ | |
70 | ".*${warning} at location 1, disabling:" \ | |
71 | " No symbol \"c\" in current context." \ | |
72 | ".*${warning} at location 2, disabling:" \ | |
73 | " No symbol \"c\" in current context." \ | |
74 | ".*Breakpoint $decimal at $fill .3 locations."] \ | |
75 | "define bp with condition c == 30" | |
76 | set bpnum2 [get_integer_valueof "\$bpnum" 0 "get bpnum2"] | |
77 | ||
78 | test_info_break 1 | |
79 | ||
80 | # Do not use runto_main, it deletes all breakpoints. | |
81 | gdb_run_cmd | |
82 | ||
83 | # Check our conditional breakpoints. | |
84 | gdb_test "" ".*Breakpoint \[0-9\]+, A::func .*" \ | |
85 | "run until A::func" | |
86 | gdb_test "print a" " = 10" | |
87 | ||
88 | gdb_test "continue" "Continuing.*Breakpoint \[0-9\]+, C::func .*" \ | |
89 | "run until C::func" | |
90 | gdb_test "print c" " = 30" | |
91 | ||
92 | # No more hits! | |
93 | gdb_continue_to_end | |
94 | ||
95 | test_info_break 2 | |
96 | } | |
97 | ||
98 | # Start GDB with two breakpoints and define the conditions separately. | |
99 | ||
100 | proc setup_bps {} { | |
101 | global srcfile binfile srcfile2 | |
102 | global bpnum1 bpnum2 bp_location warning | |
103 | ||
104 | clean_restart ${binfile} | |
105 | ||
106 | # Define the breakpoints. | |
107 | gdb_breakpoint "func" | |
108 | set bpnum1 [get_integer_valueof "\$bpnum" 0 "get bpnum1"] | |
109 | ||
110 | gdb_breakpoint "func" | |
111 | set bpnum2 [get_integer_valueof "\$bpnum" 0 "get bpnum2"] | |
112 | ||
113 | # Defining a condition on 'a' disables 2 locations. | |
114 | gdb_test "cond $bpnum1 a == 10" \ | |
115 | [multi_line \ | |
116 | "$warning at location ${bpnum1}.1, disabling:" \ | |
117 | " No symbol \"a\" in current context." \ | |
118 | "$warning at location ${bpnum1}.3, disabling:" \ | |
119 | " No symbol \"a\" in current context."] | |
120 | ||
121 | # Defining a condition on 'c' disables 2 locations. | |
122 | gdb_test "cond $bpnum2 c == 30" \ | |
123 | [multi_line \ | |
124 | "$warning at location ${bpnum2}.1, disabling:" \ | |
125 | " No symbol \"c\" in current context." \ | |
126 | "$warning at location ${bpnum2}.2, disabling:" \ | |
127 | " No symbol \"c\" in current context."] | |
128 | } | |
129 | ||
130 | # Scenario 2: Define breakpoints unconditionally, and then define | |
131 | # conditions using the "cond N <cond>" syntax. Expect that the | |
132 | # locations where <cond> is not evaluatable are disabled. Run the | |
133 | # program, check that we hit the enabled locations only. | |
134 | ||
135 | with_test_prefix "scenario 2" { | |
136 | setup_bps | |
137 | ||
138 | test_info_break 1 | |
139 | ||
140 | # Do not use runto_main, it deletes all breakpoints. | |
141 | gdb_run_cmd | |
142 | ||
143 | # Check that we hit enabled locations only. | |
144 | gdb_test "" ".*Breakpoint \[0-9\]+, A::func .*" \ | |
145 | "run until A::func" | |
146 | gdb_test "print a" " = 10" | |
147 | ||
148 | gdb_test "continue" "Continuing.*Breakpoint \[0-9\]+, C::func .*" \ | |
149 | "run until C::func" | |
150 | gdb_test "print c" " = 30" | |
151 | ||
152 | # No more hits! | |
153 | gdb_continue_to_end | |
154 | ||
155 | test_info_break 2 | |
156 | } | |
157 | ||
158 | # Test the breakpoint location enabled states. | |
159 | ||
160 | proc check_bp_locations {bpnum states msg} { | |
161 | global fill | |
162 | ||
163 | set expected ".*${bpnum}.1${fill} [lindex $states 0] ${fill}\r\n" | |
164 | append expected "${bpnum}.2${fill} [lindex $states 1] ${fill}\r\n" | |
165 | append expected "${bpnum}.3${fill} [lindex $states 2] ${fill}" | |
166 | if {[lsearch $states N*] >= 0} { | |
167 | append expected "\r\n\\(\\*\\): Breakpoint condition is invalid at this location." | |
168 | } | |
169 | ||
170 | gdb_test "info break $bpnum" $expected "check bp $bpnum $msg" | |
171 | } | |
172 | ||
173 | # Scenario 3: Apply misc. checks on the already-defined breakpoints. | |
174 | ||
175 | with_test_prefix "scenario 3" { | |
176 | setup_bps | |
177 | ||
178 | gdb_test "cond $bpnum1 c == 30" \ | |
179 | [multi_line \ | |
180 | "${warning} at location ${bpnum1}.1, disabling:" \ | |
181 | " No symbol \"c\" in current context." \ | |
182 | "${warning} at location ${bpnum1}.2, disabling:" \ | |
183 | " No symbol \"c\" in current context." \ | |
184 | "Breakpoint ${bpnum1}'s condition is now valid at location 3, enabling."] \ | |
185 | "change the condition of bp 1" | |
186 | check_bp_locations $bpnum1 {N* N* y} "after changing the condition" | |
187 | ||
188 | gdb_test "cond $bpnum1" \ | |
189 | [multi_line \ | |
190 | "Breakpoint ${bpnum1}'s condition is now valid at location 1, enabling." \ | |
191 | "Breakpoint ${bpnum1}'s condition is now valid at location 2, enabling." \ | |
192 | "Breakpoint ${bpnum1} now unconditional."] \ | |
193 | "reset the condition of bp 1" | |
194 | check_bp_locations $bpnum1 {y y y} "after resetting the condition" | |
195 | ||
196 | gdb_test_no_output "disable ${bpnum2}.2" | |
197 | check_bp_locations $bpnum2 {N* N* y} "after disabling loc 2" | |
198 | ||
199 | gdb_test "cond $bpnum2" ".*" "reset the condition of bp 2" | |
200 | check_bp_locations $bpnum2 {y n y} "loc 2 should remain disabled" | |
201 | ||
202 | gdb_test_no_output "disable ${bpnum2}.3" | |
203 | check_bp_locations $bpnum2 {y n n} "after disabling loc 3" | |
204 | ||
205 | gdb_test "cond $bpnum2 c == 30" \ | |
206 | [multi_line \ | |
207 | "${warning} at location ${bpnum2}.1, disabling:" \ | |
208 | " No symbol \"c\" in current context."] \ | |
209 | "re-define a condition" | |
210 | check_bp_locations $bpnum2 {N* N* n} "loc 3 should remain disabled" | |
211 | ||
212 | gdb_test "enable ${bpnum2}.1" \ | |
213 | "Breakpoint ${bpnum2}'s condition is invalid at location 1, cannot enable." \ | |
214 | "reject enabling a location that is disabled-by-cond" | |
215 | check_bp_locations $bpnum2 {N* N* n} "after enable attempt" | |
216 | ||
217 | gdb_test "cond $bpnum2 garbage" \ | |
218 | "No symbol \"garbage\" in current context." \ | |
219 | "reject condition if bad for all locations" | |
220 | ||
221 | gdb_test_no_output "delete $bpnum1" | |
222 | ||
223 | # Do not use runto_main, it deletes all breakpoints. | |
224 | gdb_breakpoint "main" | |
225 | gdb_run_cmd | |
226 | gdb_test "" ".*reakpoint .*, main .*${srcfile}.*" "start" | |
227 | ||
228 | # The second BP's locations are all disabled. No more hits! | |
229 | gdb_continue_to_end | |
230 | } | |
733d554a TBA |
231 | |
232 | # Scenario 4: Test the '-force'/'-force-condition' flag. | |
233 | ||
234 | with_test_prefix "force" { | |
235 | clean_restart ${binfile} | |
236 | ||
237 | gdb_breakpoint "func" | |
238 | # Pick a condition that is invalid at every location. | |
239 | set bpnum1 [get_integer_valueof "\$bpnum" 0 "get bpnum1"] | |
240 | gdb_test "cond -force $bpnum1 foo" \ | |
241 | [multi_line \ | |
242 | "${warning} at location ${bpnum1}.1, disabling:" \ | |
243 | " No symbol \"foo\" in current context." \ | |
244 | "${warning} at location ${bpnum1}.2, disabling:" \ | |
245 | " No symbol \"foo\" in current context." \ | |
246 | "${warning} at location ${bpnum1}.3, disabling:" \ | |
247 | " No symbol \"foo\" in current context."] \ | |
248 | "force the condition of bp 1" | |
249 | check_bp_locations $bpnum1 {N* N* N*} "after forcing the condition" | |
250 | ||
251 | # Now with the 'break' command. | |
252 | gdb_breakpoint "func -force-condition if baz" | |
253 | set bpnum2 [get_integer_valueof "\$bpnum" 0 "get bpnum2"] | |
254 | check_bp_locations $bpnum2 {N* N* N*} "set using the break command" | |
255 | } |