]>
Commit | Line | Data |
---|---|---|
b811d2c2 | 1 | # Copyright 2008-2020 Free Software Foundation, Inc. |
edb3359d DJ |
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 | ||
8980e177 PA |
16 | load_lib mi-support.exp |
17 | set MIFLAGS "-i=mi" | |
18 | ||
efc9d70a TT |
19 | standard_testfile .c inline-markers.c |
20 | ||
5b362f04 | 21 | if {[prepare_for_testing "failed to prepare" $testfile \ |
1f960ced | 22 | [list $srcfile $srcfile2] {debug additional_flags=-Winline}]} { |
edb3359d DJ |
23 | return -1 |
24 | } | |
25 | ||
019ebafc | 26 | gdb_test_no_output "set listsize 1" |
edb3359d DJ |
27 | |
28 | runto_main | |
29 | ||
4c93b1db | 30 | get_compiler_info |
edb3359d DJ |
31 | get_debug_format |
32 | if { [skip_inline_frame_tests] } { | |
5b362f04 | 33 | untested "skipping inline frame tests" |
edb3359d DJ |
34 | return |
35 | } | |
36 | ||
37 | # First, check that the things we expected to be inlined really were, | |
38 | # and those that shouldn't be weren't. | |
39 | set line1 [gdb_get_line_number "set breakpoint 1 here" ${srcfile2}] | |
40 | gdb_breakpoint $srcfile2:$line1 | |
41 | set line2 [gdb_get_line_number "set breakpoint 2 here" ${srcfile2}] | |
42 | gdb_breakpoint $srcfile2:$line2 | |
43 | ||
44 | gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (1)" | |
45 | gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*main.*" \ | |
46 | "backtrace from bar (1)" | |
47 | gdb_test "up" "#1 .*func1.*" "up from bar (1)" | |
48 | gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (1)" | |
49 | ||
50 | gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (2)" | |
51 | gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*func2.*#3 .*main.*" \ | |
52 | "backtrace from bar (2)" | |
53 | gdb_test "up" "#1 .*func1.*" "up from bar (2)" | |
54 | gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (2)" | |
55 | gdb_test "up" "#2 .*func2.*" "up from func1 (2)" | |
56 | gdb_test "info frame" ".*inlined into frame.*" "func2 inlined (2)" | |
57 | ||
58 | gdb_test "continue" ".*set breakpoint 2 here.*" "continue to marker" | |
59 | gdb_test "backtrace" "#0 marker.*#1 .*main.*" "backtrace from marker" | |
60 | gdb_test "info frame" ".*called by frame.*" "marker not inlined" | |
61 | ||
62 | # Next, check that we can next over inlined functions. We should not end up | |
63 | # inside any of them. | |
64 | delete_breakpoints | |
65 | runto_main | |
66 | ||
67 | # The lines before the first inlined call. | |
68 | set first "x = 7|y = 8" | |
69 | ||
70 | # Some extra lines that end up in our stepping due to code motion. | |
71 | set opt "start of main|result = 0" | |
72 | ||
73 | # We start this test with a "list" instead of a "next", in case the | |
74 | # first non-prologue instruction in main comes from the inlined function. | |
75 | set msg "next over inlined functions" | |
76 | gdb_test_multiple "list" $msg { | |
77 | -re "($first|result = func1|result = func2|$opt).*$gdb_prompt $" { | |
78 | send_gdb "next\r" | |
79 | exp_continue | |
80 | } | |
81 | -re "marker \\\(\\\);\r\n$gdb_prompt $" { | |
82 | pass $msg | |
83 | } | |
84 | } | |
85 | ||
86 | # Check that when next shows the call of func1, it has not happened yet. | |
87 | runto_main | |
88 | ||
89 | # Like the return value of gdb_test: -1 something is wrong, 0 passed, 1 failed. | |
90 | set bt_test -1 | |
91 | set x_test -1 | |
92 | set func1_step -1 | |
93 | ||
94 | set last_was_func1_call 0 | |
95 | set msg "next past inlined func1" | |
96 | gdb_test_multiple "list" $msg { | |
97 | -re "($first|$opt).*$gdb_prompt $" { | |
98 | set last_was_func1_call 0 | |
99 | send_gdb "next\r" | |
100 | exp_continue | |
101 | } | |
102 | -re "result = func1 \\\(\\\);\r\n$gdb_prompt $" { | |
103 | # Check whether x has been set. If 0, we may be doing something | |
104 | # else associated with this line besides the inlined call - e.g. | |
105 | # loading the address of result. If 7, we may be at the call site. | |
106 | # If 15, though, we might be past the call and back at the store to | |
107 | # result - that's OK, as long as we weren't just here (see | |
108 | # func1_step above). | |
109 | set x_val -1 | |
110 | gdb_test_multiple "print x" "" { | |
111 | -re "\\\$$decimal = (\[0-9\]*)\r\n$gdb_prompt $" { | |
112 | set x_val $expect_out(1,string) | |
113 | } | |
114 | -re "$gdb_prompt $" { } | |
115 | } | |
116 | if { $x_val == 0 || $x_val == 7 } { | |
117 | if { $x_test != 1 } { | |
118 | set x_test 0 | |
119 | } | |
120 | } elseif { $x_val == 15 } { | |
121 | if { $func1_step == -1 } { | |
122 | # We passed func1 without stopping at the call site. | |
123 | set x_test 1 | |
124 | } | |
125 | } else { | |
126 | set x_test 1 | |
127 | } | |
128 | ||
129 | # func1 should not show up on backtraces if we are at its call | |
130 | # site. | |
131 | if { $bt_test != 1 } { | |
132 | set bt_test [gdb_test "backtrace" "#0 \[^#]*main.*" ""] | |
133 | } | |
134 | ||
135 | # When we next over func1, we should not return to the same | |
136 | # line. But we might go past the line, according to source | |
137 | # code order, and then come back. A valid but odd layout is | |
138 | # body of func1, load result's address into a register using | |
139 | # the source location of "result = 0" several lines down, and | |
140 | # then return to this line for the store. GCC 4.3 does that | |
141 | # on ARM. | |
142 | if { $last_was_func1_call } { | |
143 | set func1_step 1 | |
144 | } elseif { $func1_step == -1 } { | |
145 | set func1_step 0 | |
146 | } | |
147 | set last_was_func1_call 1 | |
148 | ||
149 | send_gdb "next\r" | |
150 | exp_continue | |
151 | } | |
152 | ||
153 | -re "result = func2 \\\(\\\);\r\n$gdb_prompt $" { | |
154 | pass $msg | |
155 | } | |
156 | } | |
157 | ||
158 | if { $x_test == 0 } { | |
159 | pass "print x before func1" | |
160 | } else { | |
161 | fail "print x before func1" | |
162 | } | |
163 | ||
164 | if { $bt_test == 0 } { | |
165 | pass "backtrace does not include func1" | |
166 | } else { | |
167 | fail "backtrace does not include func1" | |
168 | } | |
169 | ||
170 | if { $bt_test == 0 } { | |
171 | pass "stepped over call to func1" | |
172 | } else { | |
173 | fail "stepped over call to func1" | |
174 | } | |
175 | ||
176 | # Next, check that we can single step into inlined functions. We should always | |
177 | # "stop" at the call sites before entering them. | |
178 | runto_main | |
179 | ||
180 | set msg "step into func1" | |
181 | set saw_call_site 0 | |
182 | gdb_test_multiple "list" $msg { | |
183 | -re "($first|$opt).*$gdb_prompt $" { | |
184 | send_gdb "step\r" | |
185 | exp_continue | |
186 | } | |
187 | -re "result = func1.*$gdb_prompt $" { | |
188 | set saw_call_site 1 | |
189 | send_gdb "step\r" | |
190 | exp_continue | |
191 | } | |
192 | -re "func1 \\\(\\\) at .*\r\n$decimal.*bar \\\(\\\);\r\n$gdb_prompt $" { | |
193 | if { $saw_call_site } { | |
194 | pass $msg | |
195 | } else { | |
196 | fail $msg | |
197 | } | |
198 | } | |
199 | } | |
200 | ||
201 | # Check finish out of an inlined function. | |
202 | set msg "finish from func1" | |
203 | gdb_test_multiple "finish" $msg { | |
204 | -re "result = func1 \\\(\\\);\r\n$gdb_prompt $" { | |
205 | pass $msg | |
206 | } | |
207 | -re "($first|$opt).*$gdb_prompt $" { | |
208 | # Whoops. We finished, but ended up back at an earlier line. Keep | |
209 | # trying. | |
210 | send_gdb "step\r" | |
211 | exp_continue | |
212 | } | |
213 | -re "func1 \\\(\\\) at .*\r\n$decimal.*bar \\\(\\\);\r\n$gdb_prompt $" { | |
214 | send_gdb "finish\r" | |
215 | exp_continue | |
216 | } | |
217 | } | |
218 | ||
219 | # Test some corner cases involving consecutive inlined functions. | |
220 | set line3 [gdb_get_line_number "set breakpoint 3 here"] | |
221 | gdb_breakpoint $line3 | |
222 | gdb_continue_to_breakpoint "consecutive func1" | |
223 | ||
224 | gdb_test "next" ".*func1 .*first call.*" "next to first func1" | |
225 | set msg "next to second func1" | |
226 | gdb_test_multiple "next" $msg { | |
227 | -re ".*func1 .*second call.*$gdb_prompt $" { | |
228 | pass $msg | |
229 | } | |
230 | -re ".*marker .*$gdb_prompt $" { | |
231 | # This assembles to two consecutive call instructions. | |
232 | # Both appear to be at the same line, because they're | |
233 | # in the body of the same inlined function. This is | |
234 | # reasonable for the line table. GDB should take the | |
235 | # containing block and/or function into account when | |
236 | # deciding how far to step. The single line table entry | |
237 | # is actually two consecutive instances of the same line. | |
238 | kfail gdb/NNNN $msg | |
239 | } | |
240 | } | |
241 | ||
242 | # It is easier when the two inlined functions are not on the same line. | |
243 | set line4 [gdb_get_line_number "set breakpoint 4 here"] | |
244 | gdb_breakpoint $line4 | |
245 | gdb_continue_to_breakpoint "func1 then func3" | |
246 | ||
247 | gdb_test "next" ".*func1 \\\(\\\);" "next to func1 before func3" | |
248 | gdb_test "next" ".*func3 \\\(\\\);" "next to func3" | |
249 | ||
250 | # Test finishing out of one thing and into another. | |
251 | set line5 [gdb_get_line_number "set breakpoint 5 here"] | |
252 | gdb_breakpoint $line5 | |
253 | gdb_continue_to_breakpoint "finish into func1" | |
254 | ||
255 | gdb_test "next" ".*marker \\\(\\\);" "next to finish marker" | |
256 | gdb_test "step" ".*set breakpoint 2 here.*" "step into finish marker" | |
b4cbb4a3 EBM |
257 | |
258 | # Some architectures will have one or more instructions after | |
259 | # the call instruction which still are part of the call sequence, | |
260 | # so it should be expected to return to the caller line after issue | |
261 | # a 'finish' command. | |
262 | gdb_test_multiple "finish" "finish from marker" { | |
263 | -re "func1 \\\(\\\);.*\r\n$gdb_prompt $" { | |
264 | pass "finish from marker to func1" | |
265 | } | |
266 | -re "marker \\\(\\\);.*\r\n$gdb_prompt $" { | |
267 | pass "finish from marker" | |
268 | gdb_test "step" "func1 \\\(\\\);.*" "step after marker to reach func1" | |
269 | } | |
270 | } | |
edb3359d DJ |
271 | |
272 | gdb_test "step" "bar \\\(\\\);" "step into func1 for finish" | |
273 | gdb_test "finish" "func3 \\\(\\\);" "finish from func1 to func3" | |
274 | ||
275 | # Test a deeper call stack. | |
276 | set line6 [gdb_get_line_number "set breakpoint 6 here"] | |
277 | gdb_breakpoint $line6 | |
278 | gdb_continue_to_breakpoint "before the outer_inline call" | |
279 | gdb_test "step" "marker \\\(\\\) at .*" "reach 1 the outer_inline call" | |
b4cbb4a3 EBM |
280 | gdb_test_multiple "finish" "finish from marker" { |
281 | -re "main \\\(\\\) at .*outer_inline2 \\\(\\\);.*\r\n$gdb_prompt $" { | |
282 | pass "reach outer_inline2" | |
283 | } | |
284 | -re "main \\\(\\\) at .*marker \\\(\\\);.*\r\n$gdb_prompt $" { | |
285 | pass "finish from marker" | |
286 | gdb_test "step" "outer_inline2 \\\(\\\);.*" "step after marker to reach outer_inline2" | |
287 | } | |
288 | } | |
edb3359d DJ |
289 | gdb_test "bt" "#0 main.*" "backtrace at main of outer_inline" |
290 | gdb_test "step" "outer_inline2 \\\(\\\) at .*" "enter outer_inline2" | |
291 | gdb_test "bt" "#0 outer_inline2.*#1 main.*" "backtrace at outer_inline2" | |
292 | gdb_test "step" "outer_inline1 \\\(\\\) at .*" "enter outer_inline1 from outer_inline2" | |
293 | ||
294 | set msg "backtrace at outer_inline1" | |
295 | gdb_test_multiple "bt" $msg { | |
296 | -re "#0 outer_inline1.*#1 outer_inline2.*#2 main.*$gdb_prompt $" { | |
297 | pass $msg | |
298 | } | |
299 | -re "#0 $hex in outer_inline1.*#1 outer_inline2.*#2 main.*$gdb_prompt $" { | |
300 | # Binutils PR gas/6717. Gas moves .loc past .p2align and the | |
301 | # leading nop of the inlined call appears to be on the same line | |
302 | # as main's call to marker. | |
303 | xfail $msg | |
304 | gdb_test "step" "noinline \\\(\\\);" "step to call of noinline" | |
305 | } | |
306 | } | |
307 | ||
308 | gdb_test "step" "noinline \\\(\\\) at .*" "enter noinline from outer_inline1" | |
309 | gdb_test "bt" "#0 noinline.*#1 .*outer_inline1.*#2 .*outer_inline2.*#3 main.*" "backtrace at noinline from outer_inline1" | |
310 | gdb_test "step" "inlined_fn \\\(\\\) at .*" "enter inlined_fn from noinline" | |
311 | gdb_test "bt" "#0 inlined_fn.*#1 noinline.*#2 .*outer_inline1.*#3 .*outer_inline2.*#4 main.*" "backtrace at inlined_fn from noinline" | |
312 | gdb_test "info frame" ".*inlined into frame.*" "inlined_fn from noinline inlined" | |
313 | gdb_test "up" "#1 noinline.*" "up to noinline" | |
314 | gdb_test "info frame" ".*\n called by frame.*" "noinline from outer_inline1 not inlined" | |
315 | gdb_test "up" "#2 .*outer_inline1.*" "up to outer_inline1" | |
316 | gdb_test "info frame" ".*inlined into frame.*" "outer_inline1 inlined" | |
317 | gdb_test "up" "#3 .*outer_inline2.*" "up to outer_inline2" | |
318 | gdb_test "info frame" ".*inlined into frame.*" "outer_inline2 inlined" | |
319 | gdb_test "up" "#4 main.*" "up from outer_inline2" | |
320 | gdb_test "info frame" ".*\n caller of frame.*" "main not inlined" | |
8980e177 PA |
321 | |
322 | gdb_exit | |
323 | ||
324 | # Send a CLI "step" command over MI. CLI_OUTPUT_RE is a regexp that | |
325 | # matches the expected CLI output. MESSAGE is used as test message. | |
326 | ||
327 | proc mi_cli_step {cli_output_re message} { | |
328 | global mi_gdb_prompt | |
329 | global srcfile | |
330 | global decimal | |
331 | ||
332 | send_gdb "interpreter-exec console \"step\"\n" | |
333 | gdb_expect { | |
334 | -re "\\^running\r\n\\*running,thread-id=\"all\"\r\n${mi_gdb_prompt}${cli_output_re}" { | |
335 | pass $message | |
336 | } | |
337 | timeout { | |
338 | fail "$message (timeout)" | |
339 | } | |
340 | eof { | |
341 | fail "$message (eof)" | |
342 | } | |
343 | } | |
344 | ||
345 | # mi_expect_stop handles "set mi-async on/off" differences. | |
346 | mi_expect_stop "end-stepping-range" "\[^\r\n\]*" "" ".*$srcfile" "$decimal" \ | |
347 | "" "got *stopped for $message" | |
348 | } | |
349 | ||
350 | # Test that stepping into an inlined function with the CLI "step" | |
351 | # command run while the top interpreter is MI results in the expected | |
352 | # CLI output sent to MI's console. | |
353 | with_test_prefix "mi" { | |
354 | if [mi_gdb_start] { | |
355 | continue | |
356 | } | |
357 | mi_gdb_load ${binfile} | |
358 | mi_runto main | |
359 | ||
360 | set line_number [gdb_get_line_number "set mi break here"] | |
361 | mi_gdb_test "-break-insert ${srcfile}:${line_number}" \ | |
362 | {\^done,bkpt=.number="2",type="breakpoint".*\}} \ | |
363 | "set breakpoint" | |
364 | ||
365 | mi_execute_to "exec-continue" "breakpoint-hit" "main" "" ".*" ".*" \ | |
366 | { "" "disp=\"keep\"" } "breakpoint hit" | |
367 | ||
368 | incr line_number 2 | |
369 | ||
370 | # Step to the line that does an inline call. | |
371 | set re "~\"$line_number\\\\t result = func1 \\(\\);\\\\n\"\r\n" | |
372 | mi_cli_step "${re}" "step to inline call" | |
373 | ||
374 | # Step into the inlined function. | |
375 | set re [multi_line \ | |
376 | "~\"func1 \\(\\) at .*$srcfile:$decimal\\\\n\"" \ | |
377 | "~\"$decimal\\\\t bar \\(\\);\\\\n\"\r\n"] | |
378 | mi_cli_step "${re}" "step into inline call" | |
379 | } |