]>
Commit | Line | Data |
---|---|---|
3a58abaf AM |
1 | infcall.c <unwind_on_signal_p>: |
2 | Revert the change of: gdb-6.8-inlining.patch | |
3 | causing: FAIL: gdb.base/unwindonsignal.exp: unwindonsignal, stack unwound | |
4 | ||
5 | resume() -> target_resume() move of clear_inline_frame_state() is for: | |
6 | gdb.mi/mi-nsmoribund.exp | |
7 | ||
8 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.c | |
9 | =================================================================== | |
10 | --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-bt.c 2009-03-06 19:07:30.000000000 +0100 | |
11 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.c 2009-03-06 19:07:30.000000000 +0100 | |
12 | @@ -13,10 +13,16 @@ | |
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 | -int x, y; | |
17 | +/* VOLATILE forces all the inlining to happen as otherwise the whole program | |
18 | + gets optimized by CSE to just simple assignments of the results. */ | |
19 | +volatile int x, y; | |
20 | volatile int result; | |
21 | ||
22 | -void bar(void); | |
23 | +inline void bar(void) | |
24 | +{ | |
25 | + x += y; /* set breakpoint 1 here */ | |
26 | +} | |
27 | + | |
28 | ||
29 | inline int func1(void) | |
30 | { | |
31 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.exp | |
32 | =================================================================== | |
33 | --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-bt.exp 2009-03-06 19:07:30.000000000 +0100 | |
34 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.exp 2009-03-06 19:07:30.000000000 +0100 | |
35 | @@ -41,18 +41,19 @@ if { [skip_inline_frame_tests] } { | |
36 | return | |
37 | } | |
38 | ||
39 | -set line1 [gdb_get_line_number "set breakpoint 1 here" ${fullsrcfile2}] | |
40 | -gdb_breakpoint $srcfile2:$line1 | |
41 | +set line1 [gdb_get_line_number "set breakpoint 1 here" ${srcfile}] | |
42 | +gdb_breakpoint $srcfile:$line1 | |
43 | ||
44 | gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (1)" | |
45 | gdb_test "backtrace" "#0 bar.*#1 .*main.*" "backtrace from bar (1)" | |
46 | -gdb_test "info frame" ".*called by frame.*" "bar not inlined" | |
47 | +gdb_test "info frame" ".*inlined into frame.*" "bar inlined" | |
48 | ||
49 | -gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (2)" | |
50 | -gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*main.*" \ | |
51 | - "backtrace from bar (2)" | |
52 | -gdb_test "up" "#1 .*func1.*" "up from bar (2)" | |
53 | -gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (2)" | |
54 | +# gcc-4.3.1 omits the line number information for (2). | |
55 | +#gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (2)" | |
56 | +#gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*main.*" \ | |
57 | +# "backtrace from bar (2)" | |
58 | +#gdb_test "up" "#1 .*func1.*" "up from bar (2)" | |
59 | +#gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (2)" | |
60 | ||
61 | gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (3)" | |
62 | gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*func2.*#3 .*main.*" \ | |
63 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.c | |
64 | =================================================================== | |
65 | --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-cmds.c 2009-03-06 19:07:30.000000000 +0100 | |
66 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.c 2009-03-06 19:07:30.000000000 +0100 | |
67 | @@ -13,13 +13,19 @@ | |
68 | You should have received a copy of the GNU General Public License | |
69 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
70 | ||
71 | -int x, y; | |
72 | +/* VOLATILE forces all the inlining to happen as otherwise the whole program | |
73 | + gets optimized by CSE to just simple assignments of the results. */ | |
74 | +volatile int x, y; | |
75 | volatile int result; | |
76 | ||
77 | -void bar(void); | |
78 | void marker(void); | |
79 | void noinline(void); | |
80 | ||
81 | +inline void bar(void) | |
82 | +{ | |
83 | + x += y; /* set breakpoint 1 here */ | |
84 | +} | |
85 | + | |
86 | inline int func1(void) | |
87 | { | |
88 | bar (); | |
89 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.exp | |
90 | =================================================================== | |
91 | --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-cmds.exp 2009-03-06 19:07:30.000000000 +0100 | |
92 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.exp 2009-03-06 19:07:30.000000000 +0100 | |
93 | @@ -45,28 +45,28 @@ if { [skip_inline_frame_tests] } { | |
94 | ||
95 | # First, check that the things we expected to be inlined really were, | |
96 | # and those that shouldn't be weren't. | |
97 | -set line1 [gdb_get_line_number "set breakpoint 1 here" ${fullsrcfile2}] | |
98 | +set line1 [gdb_get_line_number "set breakpoint 1 here" ${srcfile2}] | |
99 | gdb_breakpoint $srcfile2:$line1 | |
100 | -set line2 [gdb_get_line_number "set breakpoint 2 here" ${fullsrcfile2}] | |
101 | +set line2 [gdb_get_line_number "set breakpoint 2 here" ${srcfile2}] | |
102 | gdb_breakpoint $srcfile2:$line2 | |
103 | ||
104 | -gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (1)" | |
105 | +gdb_test "continue" "set breakpoint 1 here.*" "continue to bar (1)" | |
106 | gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*main.*" \ | |
107 | "backtrace from bar (1)" | |
108 | gdb_test "up" "#1 .*func1.*" "up from bar (1)" | |
109 | -gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (1)" | |
110 | +gdb_test "info frame" "inlined into frame.*" "func1 inlined (1)" | |
111 | ||
112 | -gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (2)" | |
113 | +gdb_test "continue" "set breakpoint 1 here.*" "continue to bar (2)" | |
114 | gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*func2.*#3 .*main.*" \ | |
115 | "backtrace from bar (2)" | |
116 | gdb_test "up" "#1 .*func1.*" "up from bar (2)" | |
117 | -gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (2)" | |
118 | +gdb_test "info frame" "inlined into frame.*" "func1 inlined (2)" | |
119 | gdb_test "up" "#2 .*func2.*" "up from func1 (2)" | |
120 | -gdb_test "info frame" ".*inlined into frame.*" "func2 inlined (2)" | |
121 | +gdb_test "info frame" "inlined into frame.*" "func2 inlined (2)" | |
122 | ||
123 | -gdb_test "continue" ".*set breakpoint 2 here.*" "continue to marker" | |
124 | +gdb_test "continue" "set breakpoint 2 here.*" "continue to marker" | |
125 | gdb_test "backtrace" "#0 marker.*#1 .*main.*" "backtrace from marker" | |
126 | -gdb_test "info frame" ".*called by frame.*" "marker not inlined" | |
127 | +gdb_test "info frame" "\n called by frame.*" "marker not inlined" | |
128 | ||
129 | # Next, check that we can next over inlined functions. We should not end up | |
130 | # inside any of them. | |
131 | @@ -201,7 +201,7 @@ set line3 [gdb_get_line_number "set brea | |
132 | gdb_breakpoint $line3 | |
133 | gdb_continue_to_breakpoint "consecutive func1" | |
134 | ||
135 | -gdb_test "next" ".*func1 .*first call.*" "next to first func1" | |
136 | +gdb_test "next" "func1 .*first call.*" "next to first func1" | |
137 | set msg "next to second func1" | |
138 | gdb_test_multiple "next" $msg { | |
139 | -re ".*func1 .*second call.*$gdb_prompt $" { | |
140 | @@ -224,16 +224,16 @@ set line4 [gdb_get_line_number "set brea | |
141 | gdb_breakpoint $line4 | |
142 | gdb_continue_to_breakpoint "func1 then func3" | |
143 | ||
144 | -gdb_test "next" ".*func1 \\\(\\\);" "next to func1 before func3" | |
145 | -gdb_test "next" ".*func3 \\\(\\\);" "next to func3" | |
146 | +gdb_test "next" "func1 \\\(\\\);" "next to func1 before func3" | |
147 | +gdb_test "next" "func3 \\\(\\\);" "next to func3" | |
148 | ||
149 | # Test finishing out of one thing and into another. | |
150 | set line5 [gdb_get_line_number "set breakpoint 5 here"] | |
151 | gdb_breakpoint $line5 | |
152 | gdb_continue_to_breakpoint "finish into func1" | |
153 | ||
154 | -gdb_test "next" ".*marker \\\(\\\);" "next to finish marker" | |
155 | -gdb_test "step" ".*set breakpoint 2 here.*" "step into finish marker" | |
156 | +gdb_test "next" "marker \\\(\\\);" "next to finish marker" | |
157 | +gdb_test "step" "set breakpoint 2 here.*" "step into finish marker" | |
158 | gdb_test "finish" "func1 \\\(\\\);" "finish from marker to func1" | |
159 | ||
160 | gdb_test "step" "bar \\\(\\\);" "step into func1 for finish" | |
161 | @@ -268,12 +268,12 @@ gdb_test "step" "noinline \\\(\\\) at .* | |
162 | gdb_test "bt" "#0 noinline.*#1 .*outer_inline1.*#2 .*outer_inline2.*#3 main.*" "backtrace at noinline from outer_inline1" | |
163 | gdb_test "step" "inlined_fn \\\(\\\) at .*" "enter inlined_fn from noinline" | |
164 | gdb_test "bt" "#0 inlined_fn.*#1 noinline.*#2 .*outer_inline1.*#3 .*outer_inline2.*#4 main.*" "backtrace at inlined_fn from noinline" | |
165 | -gdb_test "info frame" ".*inlined into frame.*" "inlined_fn from noinline inlined" | |
166 | -gdb_test "up" "#1 noinline.*" "up to noinline" | |
167 | -gdb_test "info frame" ".*\n called by frame.*" "noinline from outer_inline1 not inlined" | |
168 | -gdb_test "up" "#2 .*outer_inline1.*" "up to outer_inline1" | |
169 | -gdb_test "info frame" ".*inlined into frame.*" "outer_inline1 inlined" | |
170 | -gdb_test "up" "#3 .*outer_inline2.*" "up to outer_inline2" | |
171 | -gdb_test "info frame" ".*inlined into frame.*" "outer_inline2 inlined" | |
172 | -gdb_test "up" "#4 main.*" "up from outer_inline2" | |
173 | -gdb_test "info frame" ".*\n caller of frame.*" "main not inlined" | |
174 | +gdb_test "info frame" "inlined into frame.*" "inlined_fn from noinline inlined" | |
175 | +gdb_test "fini" "" "up to noinline" | |
176 | +gdb_test "info frame" "\n called by frame.*" "noinline from outer_inline1 not inlined" | |
177 | +gdb_test "fini" "" "up to outer_inline1" | |
178 | +gdb_test "info frame" "inlined into frame.*" "outer_inline1 inlined" | |
179 | +gdb_test "fini" "" "up to outer_inline2" | |
180 | +gdb_test "info frame" "inlined into frame.*" "outer_inline2 inlined" | |
181 | +gdb_test "fini" "" "up from outer_inline2" | |
182 | +gdb_test "info frame" " in main \[^\n\]*\n source language.*" "main not inlined" | |
183 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.c | |
184 | =================================================================== | |
185 | --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-locals.c 2009-03-06 19:07:30.000000000 +0100 | |
186 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.c 2009-03-06 19:07:30.000000000 +0100 | |
187 | @@ -13,11 +13,16 @@ | |
188 | You should have received a copy of the GNU General Public License | |
189 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
190 | ||
191 | -int x, y; | |
192 | +/* VOLATILE forces all the inlining to happen as otherwise the whole program | |
193 | + gets optimized by CSE to just simple assignments of the results. */ | |
194 | +volatile int x, y; | |
195 | volatile int result; | |
196 | volatile int *array_p; | |
197 | ||
198 | -void bar(void); | |
199 | +inline void bar(void) | |
200 | +{ | |
201 | + x += y; /* set breakpoint 1 here */ | |
202 | +} | |
203 | ||
204 | inline int func1(int arg1) | |
205 | { | |
206 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.exp | |
207 | =================================================================== | |
208 | --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-locals.exp 2009-03-06 19:07:30.000000000 +0100 | |
209 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.exp 2009-03-06 19:07:30.000000000 +0100 | |
210 | @@ -43,8 +43,8 @@ if { [skip_inline_var_tests] } { | |
211 | ||
212 | set no_frames [skip_inline_frame_tests] | |
213 | ||
214 | -set line1 [gdb_get_line_number "set breakpoint 1 here" ${fullsrcfile2}] | |
215 | -gdb_breakpoint $srcfile2:$line1 | |
216 | +set line1 [gdb_get_line_number "set breakpoint 1 here" ${srcfile}] | |
217 | +gdb_breakpoint $srcfile:$line1 | |
218 | ||
219 | gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (1)" | |
220 | ||
221 | @@ -77,6 +77,9 @@ if { ! $no_frames } { | |
222 | ||
223 | # Make sure that locals on the stack are found. This is an array to | |
224 | # prevent it from living in a register. | |
225 | +if [test_compiler_info "gcc-4-3-*"] { | |
226 | + setup_kfail *-*-* "gcc/debug.optimization" | |
227 | +} | |
228 | gdb_test "print array\[0\]" "\\\$$decimal = 0" "print local (2)" | |
229 | ||
230 | if { ! $no_frames } { | |
231 | @@ -115,4 +118,7 @@ if { ! $no_frames } { | |
232 | gdb_test "info locals" ".*arg2 = 184.*" "info locals above bar (3b)" | |
233 | } | |
234 | ||
235 | +if [test_compiler_info "gcc-4-3-*"] { | |
236 | + setup_kfail *-*-* "gcc/debug.optimization" | |
237 | +} | |
238 | gdb_test "print array\[0\]" "\\\$$decimal = 184" "print local (3)" | |
239 | Index: gdb-6.8.50.20090302/gdb/frame.c | |
240 | =================================================================== | |
241 | --- gdb-6.8.50.20090302.orig/gdb/frame.c 2009-03-06 19:07:30.000000000 +0100 | |
242 | +++ gdb-6.8.50.20090302/gdb/frame.c 2009-03-06 19:07:30.000000000 +0100 | |
243 | @@ -269,7 +269,7 @@ fprint_frame (struct ui_file *file, stru | |
244 | static struct frame_info * | |
245 | skip_inlined_frames (struct frame_info *frame) | |
246 | { | |
247 | - while (get_frame_type (frame) == INLINE_FRAME) | |
248 | + while (frame && get_frame_type (frame) == INLINE_FRAME) | |
249 | frame = get_prev_frame (frame); | |
250 | ||
251 | return frame; | |
252 | @@ -1670,6 +1670,7 @@ get_frame_address_in_block (struct frame | |
253 | { | |
254 | /* A draft address. */ | |
255 | CORE_ADDR pc = get_frame_pc (this_frame); | |
256 | + struct thread_info *tp = inferior_thread (); | |
257 | ||
258 | struct frame_info *next_frame = this_frame->next; | |
259 | ||
260 | @@ -1712,6 +1713,9 @@ get_frame_address_in_block (struct frame | |
261 | while in an inlined function, then the code address of the | |
262 | "calling" normal function should not be adjusted either. */ | |
263 | ||
264 | + if (tp->current_pc_is_notcurrent) | |
265 | + return pc - 1; | |
266 | + | |
267 | while (get_frame_type (next_frame) == INLINE_FRAME) | |
268 | next_frame = next_frame->next; | |
269 | ||
270 | @@ -1743,7 +1747,7 @@ find_frame_sal (struct frame_info *frame | |
271 | sym = inline_skipped_symbol (inferior_ptid); | |
272 | ||
273 | init_sal (sal); | |
274 | - if (SYMBOL_LINE (sym) != 0) | |
275 | + if (sym != NULL && SYMBOL_LINE (sym) != 0) | |
276 | { | |
277 | sal->symtab = SYMBOL_SYMTAB (sym); | |
278 | sal->line = SYMBOL_LINE (sym); | |
279 | Index: gdb-6.8.50.20090302/gdb/breakpoint.c | |
280 | =================================================================== | |
281 | --- gdb-6.8.50.20090302.orig/gdb/breakpoint.c 2009-03-06 19:07:30.000000000 +0100 | |
282 | +++ gdb-6.8.50.20090302/gdb/breakpoint.c 2009-03-06 19:07:30.000000000 +0100 | |
283 | @@ -57,6 +57,7 @@ | |
284 | #include "top.h" | |
285 | #include "wrapper.h" | |
286 | #include "valprint.h" | |
287 | +#include "inline-frame.h" | |
288 | ||
289 | #include "mi/mi-common.h" | |
290 | ||
291 | @@ -2902,10 +2903,24 @@ bpstat_check_breakpoint_conditions (bpst | |
292 | const struct bp_location *bl = bs->breakpoint_at; | |
293 | struct breakpoint *b = bl->owner; | |
294 | ||
295 | - if (frame_id_p (b->frame_id) | |
296 | - && !frame_id_eq (b->frame_id, get_stack_frame_id (get_current_frame ()))) | |
297 | - bs->stop = 0; | |
298 | - else if (bs->stop) | |
299 | + if (frame_id_p (b->frame_id)) | |
300 | + { | |
301 | + struct frame_info *b_frame, *frame; | |
302 | + struct frame_id b_frame_id, current_frame_id; | |
303 | + | |
304 | + b_frame = frame_find_by_id (b->frame_id); | |
305 | + | |
306 | + /* get_stack_frame_id normalizes the id to the real non-inlined function | |
307 | + by skip_inlined_frames. */ | |
308 | + b_frame_id = get_stack_frame_id (b_frame); | |
309 | + current_frame_id = get_stack_frame_id (get_current_frame ()); | |
310 | + | |
311 | + /* Completely different (inlining notwithstanding) frames? */ | |
312 | + if (!frame_id_eq (b_frame_id, current_frame_id)) | |
313 | + bs->stop = 0; | |
314 | + } | |
315 | + | |
316 | + if (bs->stop) | |
317 | { | |
318 | int value_is_zero = 0; | |
319 | ||
320 | @@ -3044,6 +3059,12 @@ bpstat_stop_status (CORE_ADDR bp_addr, p | |
321 | bs->print = 0; | |
322 | } | |
323 | bs->commands = copy_command_lines (bs->commands); | |
324 | + | |
325 | + /* Display the innermost inlined frame at a breakpont as it gives to | |
326 | + most of the available information. */ | |
327 | + if (b->type != bp_until && b->type != bp_finish) | |
328 | + while (inline_skipped_frames (ptid)) | |
329 | + step_into_inline_frame (ptid); | |
330 | } | |
331 | ||
332 | /* Print nothing for this entry if we dont stop or if we dont print. */ | |
333 | @@ -5168,9 +5189,9 @@ set_momentary_breakpoint (struct symtab_ | |
334 | { | |
335 | struct breakpoint *b; | |
336 | ||
337 | - /* If FRAME_ID is valid, it should be a real frame, not an inlined | |
338 | - one. */ | |
339 | - gdb_assert (!frame_id_inlined_p (frame_id)); | |
340 | + /* We can be returning even into an inline frame. While finish_command will | |
341 | + shortcut the case of returning _from_ an inline frame we still may be | |
342 | + returning from non-inlined frame _to_ an inlined frame. */ | |
343 | ||
344 | b = set_raw_breakpoint (sal, type); | |
345 | b->enable_state = bp_enabled; | |
346 | Index: gdb-6.8.50.20090302/gdb/inline-frame.c | |
347 | =================================================================== | |
348 | --- gdb-6.8.50.20090302.orig/gdb/inline-frame.c 2009-03-06 19:07:30.000000000 +0100 | |
349 | +++ gdb-6.8.50.20090302/gdb/inline-frame.c 2009-03-06 19:07:30.000000000 +0100 | |
350 | @@ -183,6 +183,12 @@ inline_frame_sniffer (const struct frame | |
351 | if (frame_block == NULL) | |
352 | return 0; | |
353 | ||
354 | + /* For >=2 inlined functions SKIPPED_SYMBOL needs to be different after each | |
355 | + step_into_inline_frame call. But skip_inline_frames is called only once | |
356 | + and thus SKIPPED_SYMBOL needs to be calculated by INLINE_FRAME_SNIFFER. */ | |
357 | + if (state) | |
358 | + state->skipped_symbol = NULL; | |
359 | + | |
360 | /* Calculate DEPTH, the number of inlined functions at this | |
361 | location. */ | |
362 | depth = 0; | |
363 | @@ -192,6 +198,10 @@ inline_frame_sniffer (const struct frame | |
364 | if (block_inlined_p (cur_block)) | |
365 | depth++; | |
366 | ||
367 | + if (state && depth == state->skipped_frames | |
368 | + && state->skipped_symbol == NULL) | |
369 | + state->skipped_symbol = BLOCK_FUNCTION (cur_block); | |
370 | + | |
371 | cur_block = BLOCK_SUPERBLOCK (cur_block); | |
372 | } | |
373 | ||
374 | @@ -275,7 +285,6 @@ skip_inline_frames (ptid_t ptid) | |
375 | { | |
376 | CORE_ADDR this_pc; | |
377 | struct block *frame_block, *cur_block; | |
378 | - struct symbol *last_sym = NULL; | |
379 | int skip_count = 0; | |
380 | struct inline_state *state; | |
381 | ||
382 | @@ -296,10 +305,7 @@ skip_inline_frames (ptid_t ptid) | |
383 | of BLOCK_START. */ | |
384 | if (BLOCK_START (cur_block) == this_pc | |
385 | || block_starting_point_at (this_pc, cur_block)) | |
386 | - { | |
387 | - skip_count++; | |
388 | - last_sym = BLOCK_FUNCTION (cur_block); | |
389 | - } | |
390 | + skip_count++; | |
391 | else | |
392 | break; | |
393 | } | |
394 | @@ -311,7 +317,6 @@ skip_inline_frames (ptid_t ptid) | |
395 | state = allocate_inline_frame_state (ptid); | |
396 | state->skipped_frames = skip_count; | |
397 | state->saved_pc = this_pc; | |
398 | - state->skipped_symbol = last_sym; | |
399 | ||
400 | if (skip_count != 0) | |
401 | reinit_frame_cache (); | |
402 | @@ -329,6 +334,23 @@ step_into_inline_frame (ptid_t ptid) | |
403 | reinit_frame_cache (); | |
404 | } | |
405 | ||
406 | +/* Step out of an inlined function by hiding it. */ | |
407 | + | |
408 | +void | |
409 | +step_out_of_inline_frame (ptid_t ptid) | |
410 | +{ | |
411 | + struct inline_state *state = find_inline_frame_state (ptid); | |
412 | + | |
413 | + gdb_assert (state != NULL); | |
414 | + | |
415 | + /* Simulate the caller adjustment. */ | |
416 | + if (state->skipped_frames == 0) | |
417 | + state->saved_pc--; | |
418 | + | |
419 | + state->skipped_frames++; | |
420 | + reinit_frame_cache (); | |
421 | +} | |
422 | + | |
423 | /* Return the number of hidden functions inlined into the current | |
424 | frame. */ | |
425 | ||
426 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-markers.c | |
427 | =================================================================== | |
428 | --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-markers.c 2009-03-06 19:07:30.000000000 +0100 | |
429 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-markers.c 2009-03-06 19:07:30.000000000 +0100 | |
430 | @@ -15,11 +15,6 @@ | |
431 | ||
432 | extern int x, y; | |
433 | ||
434 | -void bar(void) | |
435 | -{ | |
436 | - x += y; /* set breakpoint 1 here */ | |
437 | -} | |
438 | - | |
439 | void marker(void) | |
440 | { | |
441 | x += y; /* set breakpoint 2 here */ | |
442 | Index: gdb-6.8.50.20090302/gdb/gdbthread.h | |
443 | =================================================================== | |
444 | --- gdb-6.8.50.20090302.orig/gdb/gdbthread.h 2009-03-06 19:07:30.000000000 +0100 | |
445 | +++ gdb-6.8.50.20090302/gdb/gdbthread.h 2009-03-06 19:07:30.000000000 +0100 | |
446 | @@ -180,6 +180,12 @@ struct thread_info | |
447 | ||
448 | /* Private data used by the target vector implementation. */ | |
449 | struct private_thread_info *private; | |
450 | + | |
451 | + /* Nonzero if the current frame PC should be unwound as the caller. It is | |
452 | + used to keep the backtrace upper levels existing after finish_command into | |
453 | + an inlined frame if the current inlined function/block was ending at the | |
454 | + current PC. */ | |
455 | + int current_pc_is_notcurrent; | |
456 | }; | |
457 | ||
458 | /* Create an empty thread list, or empty the existing one. */ | |
459 | Index: gdb-6.8.50.20090302/gdb/infcmd.c | |
460 | =================================================================== | |
461 | --- gdb-6.8.50.20090302.orig/gdb/infcmd.c 2009-03-06 19:07:30.000000000 +0100 | |
462 | +++ gdb-6.8.50.20090302/gdb/infcmd.c 2009-03-06 19:07:30.000000000 +0100 | |
463 | @@ -1391,11 +1391,11 @@ finish_command_continuation (void *arg) | |
464 | struct type *value_type; | |
465 | ||
466 | value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (a->function)); | |
467 | - if (!value_type) | |
468 | + if (!SYMBOL_INLINED (a->function) && !value_type) | |
469 | internal_error (__FILE__, __LINE__, | |
470 | _("finish_command: function has no target type")); | |
471 | ||
472 | - if (TYPE_CODE (value_type) != TYPE_CODE_VOID) | |
473 | + if (value_type && TYPE_CODE (value_type) != TYPE_CODE_VOID) | |
474 | print_return_value (SYMBOL_TYPE (a->function), value_type); | |
475 | } | |
476 | ||
477 | @@ -1499,6 +1499,16 @@ finish_forward (struct symbol *function, | |
478 | ||
479 | old_chain = make_cleanup_delete_breakpoint (breakpoint); | |
480 | ||
481 | + /* We should _always_ set CURRENT_PC_IS_NOTCURRENT here to always see the | |
482 | + calling line with the message `Value returned is ...'. Currently it is | |
483 | + seen only if at least one instruction is on that source line after the | |
484 | + call instruction. We would also need to hook step_once and only clear | |
485 | + CURRENT_PC_IS_NOTCURRENT on the first step. But it would be a change of | |
486 | + general non-inlining behavior against upstream. */ | |
487 | + | |
488 | + if (get_frame_type (frame) == INLINE_FRAME) | |
489 | + tp->current_pc_is_notcurrent = 1; | |
490 | + | |
491 | tp->proceed_to_finish = 1; /* We want stop_registers, please... */ | |
492 | make_cleanup_restore_integer (&suppress_stop_observer); | |
493 | suppress_stop_observer = 1; | |
494 | @@ -1522,7 +1532,9 @@ finish_forward (struct symbol *function, | |
495 | static void | |
496 | finish_command (char *arg, int from_tty) | |
497 | { | |
498 | - struct frame_info *frame; | |
499 | + /* FIXME: Rename `current_frame' to `frame' upon a merge. */ | |
500 | + struct frame_info *current_frame, *prev_frame; | |
501 | + CORE_ADDR frame_pc; | |
502 | struct symbol *function; | |
503 | ||
504 | int async_exec = 0; | |
505 | @@ -1553,46 +1565,63 @@ finish_command (char *arg, int from_tty) | |
506 | if (!target_has_execution) | |
507 | error (_("The program is not running.")); | |
508 | ||
509 | - frame = get_prev_frame (get_selected_frame (_("No selected frame."))); | |
510 | - if (frame == 0) | |
511 | + current_frame = get_selected_frame (_("No selected frame.")); | |
512 | + frame_pc = get_frame_pc (current_frame); | |
513 | + prev_frame = get_prev_frame (current_frame); | |
514 | + if (prev_frame == 0) | |
515 | error (_("\"finish\" not meaningful in the outermost frame.")); | |
516 | ||
517 | - clear_proceed_status (); | |
518 | - | |
519 | /* Finishing from an inline frame is completely different. We don't | |
520 | try to show the "return value" - no way to locate it. So we do | |
521 | not need a completion. */ | |
522 | - if (get_frame_type (get_selected_frame (_("No selected frame."))) | |
523 | - == INLINE_FRAME) | |
524 | + if (get_frame_type (current_frame) == INLINE_FRAME) | |
525 | { | |
526 | struct thread_info *tp = inferior_thread (); | |
527 | - | |
528 | - /* Claim we are stepping in the calling frame. An empty step | |
529 | - range means that we will stop once we aren't in a function | |
530 | - called by that frame. We don't use the magic "1" value for | |
531 | - step_range_end, because then infrun will think this is nexti, | |
532 | - and not step over the rest of this inlined function call. */ | |
533 | struct symtab_and_line empty_sal; | |
534 | - init_sal (&empty_sal); | |
535 | - set_step_info (tp, frame, empty_sal); | |
536 | - tp->step_range_start = tp->step_range_end = get_frame_pc (frame); | |
537 | - tp->step_over_calls = STEP_OVER_ALL; | |
538 | + struct block *frame_block; | |
539 | ||
540 | /* Print info on the selected frame, including level number but not | |
541 | source. */ | |
542 | if (from_tty) | |
543 | { | |
544 | printf_filtered (_("Run till exit from ")); | |
545 | - print_stack_frame (get_selected_frame (NULL), 1, LOCATION); | |
546 | + print_stack_frame (current_frame, 1, LOCATION); | |
547 | } | |
548 | ||
549 | + /* Even just a single stepi would get us out of the caller function PC | |
550 | + range. */ | |
551 | + | |
552 | + frame_block = get_frame_block (current_frame, NULL); | |
553 | + | |
554 | + /* FRAME_BLOCK must be initialized and also the frame printing above must | |
555 | + be done still with the original CURRENT_PC_IS_NOTCURRENT setting. */ | |
556 | + clear_proceed_status (); | |
557 | + | |
558 | + if (frame_block && BLOCK_END (frame_block) == frame_pc) | |
559 | + { | |
560 | + step_out_of_inline_frame (tp->ptid); | |
561 | + tp->current_pc_is_notcurrent = 1; | |
562 | + normal_stop (); | |
563 | + return; | |
564 | + } | |
565 | + | |
566 | + /* Claim we are stepping in the calling frame. An empty step | |
567 | + range means that we will stop once we aren't in a function | |
568 | + called by that frame. We don't use the magic "1" value for | |
569 | + step_range_end, because then infrun will think this is nexti, | |
570 | + and not step over the rest of this inlined function call. */ | |
571 | + init_sal (&empty_sal); | |
572 | + set_step_info (tp, prev_frame, empty_sal); | |
573 | + tp->step_range_start = tp->step_range_end = get_frame_pc (prev_frame); | |
574 | + tp->step_over_calls = STEP_OVER_ALL; | |
575 | + | |
576 | proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1); | |
577 | return; | |
578 | } | |
579 | ||
580 | /* Find the function we will return from. */ | |
581 | ||
582 | - function = find_pc_function (get_frame_pc (get_selected_frame (NULL))); | |
583 | + function = find_pc_function (frame_pc); | |
584 | ||
585 | /* Print info on the selected frame, including level number but not | |
586 | source. */ | |
587 | @@ -1606,10 +1635,14 @@ finish_command (char *arg, int from_tty) | |
588 | print_stack_frame (get_selected_frame (NULL), 1, LOCATION); | |
589 | } | |
590 | ||
591 | + /* Frames printing above must be done still with the original | |
592 | + CURRENT_PC_IS_NOTCURRENT setting. */ | |
593 | + clear_proceed_status (); | |
594 | + | |
595 | if (execution_direction == EXEC_REVERSE) | |
596 | finish_backward (function); | |
597 | else | |
598 | - finish_forward (function, frame); | |
599 | + finish_forward (function, prev_frame); | |
600 | } | |
601 | \f | |
602 | ||
603 | Index: gdb-6.8.50.20090302/gdb/infrun.c | |
604 | =================================================================== | |
605 | --- gdb-6.8.50.20090302.orig/gdb/infrun.c 2009-03-06 19:07:30.000000000 +0100 | |
606 | +++ gdb-6.8.50.20090302/gdb/infrun.c 2009-03-06 19:07:30.000000000 +0100 | |
607 | @@ -1152,8 +1152,6 @@ a command like `return' or `jump' to con | |
608 | step = 0; | |
609 | } | |
610 | ||
611 | - clear_inline_frame_state (resume_ptid); | |
612 | - | |
613 | if (debug_displaced | |
614 | && use_displaced_stepping (gdbarch) | |
615 | && tp->trap_expected) | |
616 | @@ -1205,6 +1203,8 @@ clear_proceed_status_thread (struct thre | |
617 | ||
618 | /* Discard any remaining commands or status from previous stop. */ | |
619 | bpstat_clear (&tp->stop_bpstat); | |
620 | + | |
621 | + tp->current_pc_is_notcurrent = 0; | |
622 | } | |
623 | ||
624 | static int | |
625 | Index: gdb-6.8.50.20090302/gdb/target.c | |
626 | =================================================================== | |
627 | --- gdb-6.8.50.20090302.orig/gdb/target.c 2009-03-06 19:07:26.000000000 +0100 | |
628 | +++ gdb-6.8.50.20090302/gdb/target.c 2009-03-06 19:07:30.000000000 +0100 | |
629 | @@ -41,6 +41,7 @@ | |
630 | #include "target-descriptions.h" | |
631 | #include "gdbthread.h" | |
632 | #include "solib.h" | |
633 | +#include "inline-frame.h" | |
634 | ||
635 | static void target_info (char *, int); | |
636 | ||
637 | @@ -1925,6 +1926,7 @@ target_resume (ptid_t ptid, int step, en | |
638 | { | |
639 | struct target_ops *t; | |
640 | ||
641 | + clear_inline_frame_state (ptid); | |
642 | dcache_invalidate (target_dcache); | |
643 | ||
644 | for (t = current_target.beneath; t != NULL; t = t->beneath) | |
645 | Index: gdb-6.8.50.20090302/gdb/inline-frame.h | |
646 | =================================================================== | |
647 | --- gdb-6.8.50.20090302.orig/gdb/inline-frame.h 2009-03-06 19:07:30.000000000 +0100 | |
648 | +++ gdb-6.8.50.20090302/gdb/inline-frame.h 2009-03-06 19:07:30.000000000 +0100 | |
649 | @@ -43,6 +43,10 @@ void clear_inline_frame_state (ptid_t pt | |
650 | ||
651 | void step_into_inline_frame (ptid_t ptid); | |
652 | ||
653 | +/* Step out of an inlined function by hiding it. */ | |
654 | + | |
655 | +void step_out_of_inline_frame (ptid_t ptid); | |
656 | + | |
657 | /* Return the number of hidden functions inlined into the current | |
658 | frame. */ | |
659 | ||
660 | Index: gdb-6.8.50.20090302/gdb/infcall.c | |
661 | =================================================================== | |
662 | --- gdb-6.8.50.20090302.orig/gdb/infcall.c 2009-03-06 19:07:30.000000000 +0100 | |
663 | +++ gdb-6.8.50.20090302/gdb/infcall.c 2009-03-06 19:07:30.000000000 +0100 | |
664 | @@ -898,8 +898,15 @@ The program being debugged exited while | |
665 | ||
666 | if (unwind_on_signal_p) | |
667 | { | |
668 | - /* The user wants the context restored. Calling error will | |
669 | - run inf_status_cleanup, which does all the work. */ | |
670 | + /* The user wants the context restored. */ | |
671 | + | |
672 | + /* We must get back to the frame we were before the | |
673 | + dummy call. */ | |
674 | + dummy_frame_pop (dummy_id); | |
675 | + | |
676 | + /* We also need to restore inferior status to that before the | |
677 | + dummy call. */ | |
678 | + restore_inferior_status (inf_status); | |
679 | ||
680 | /* FIXME: Insert a bunch of wrap_here; name can be very | |
681 | long if it's a C++ name with arguments and stuff. */ | |
682 | Index: gdb-6.8.50.20090302/gdb/dwarf2read.c | |
683 | =================================================================== | |
684 | --- gdb-6.8.50.20090302.orig/gdb/dwarf2read.c 2009-03-06 19:07:30.000000000 +0100 | |
685 | +++ gdb-6.8.50.20090302/gdb/dwarf2read.c 2009-03-06 19:07:40.000000000 +0100 | |
686 | @@ -3463,6 +3463,7 @@ read_func_scope (struct die_info *die, s | |
687 | unsigned die_children = 0; | |
688 | struct attribute *call_line, *call_file; | |
689 | int inlined_func = (die->tag == DW_TAG_inlined_subroutine); | |
690 | + struct type *type; | |
691 | ||
692 | if (inlined_func) | |
693 | { | |
694 | @@ -3504,7 +3505,10 @@ read_func_scope (struct die_info *die, s | |
695 | add_to_cu_func_list (name, lowpc, highpc, cu); | |
696 | ||
697 | new = push_context (0, lowpc); | |
698 | - new->name = new_symbol (die, read_type_die (die, cu), cu); | |
699 | + type = read_type_die (die, cu); | |
700 | + gdb_assert (type != NULL); | |
701 | + new->name = new_symbol (die, type, cu); | |
702 | + gdb_assert (TYPE_CODE (SYMBOL_TYPE (new->name)) == TYPE_CODE_FUNC); | |
703 | ||
704 | /* If there is a location expression for DW_AT_frame_base, record | |
705 | it. */ | |
706 | @@ -8746,6 +8750,7 @@ read_type_die (struct die_info *die, str | |
707 | break; | |
708 | case DW_TAG_subprogram: | |
709 | case DW_TAG_subroutine_type: | |
710 | + case DW_TAG_inlined_subroutine: | |
711 | this_type = read_subroutine_type (die, cu); | |
712 | break; | |
713 | case DW_TAG_array_type: |