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