]>
Commit | Line | Data |
---|---|---|
3a58abaf AM |
1 | http://sourceware.org/ml/gdb-patches/2008-07/msg00442.html |
2 | with pre-applied and post-unapplied (the patch is currently 2008-12-06 not | |
3 | applied upstream) | |
4 | http://sourceware.org/ml/gdb-patches/2008-07/msg00317.html | |
5 | ||
6 | Removed dwarf_expr_frame_base NULL check duplicity with *-vla.patch. | |
7 | ||
d566d21e | 8 | Index: gdb-6.8.50.20090302/gdb/NEWS |
3a58abaf | 9 | =================================================================== |
d566d21e | 10 | --- gdb-6.8.50.20090302.orig/gdb/NEWS 2009-03-21 21:06:02.000000000 +0100 |
11 | +++ gdb-6.8.50.20090302/gdb/NEWS 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
12 | @@ -1,6 +1,11 @@ |
13 | What has changed in GDB? | |
14 | (Organized release by release) | |
15 | ||
16 | +*** Fedora changes | |
17 | + | |
18 | +* Inlined functions are now supported. They show up in backtraces, and | |
19 | +the "step", "next", and "finish" commands handle them automatically. | |
20 | + | |
21 | *** Changes since GDB 6.8 | |
22 | ||
23 | * GDB now has support for multi-byte and wide character sets on the | |
d566d21e | 24 | Index: gdb-6.8.50.20090302/gdb/block.c |
3a58abaf | 25 | =================================================================== |
d566d21e | 26 | --- gdb-6.8.50.20090302.orig/gdb/block.c 2009-03-21 21:06:02.000000000 +0100 |
27 | +++ gdb-6.8.50.20090302/gdb/block.c 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
28 | @@ -47,8 +47,16 @@ contained_in (const struct block *a, con |
29 | { | |
30 | if (!a || !b) | |
31 | return 0; | |
32 | - return BLOCK_START (a) >= BLOCK_START (b) | |
33 | - && BLOCK_END (a) <= BLOCK_END (b); | |
34 | + | |
35 | + do | |
36 | + { | |
37 | + if (a == b) | |
38 | + return 1; | |
39 | + a = BLOCK_SUPERBLOCK (a); | |
40 | + } | |
41 | + while (a != NULL); | |
42 | + | |
43 | + return 0; | |
44 | } | |
45 | ||
46 | ||
47 | @@ -60,12 +68,21 @@ contained_in (const struct block *a, con | |
48 | struct symbol * | |
49 | block_linkage_function (const struct block *bl) | |
50 | { | |
51 | - while (BLOCK_FUNCTION (bl) == 0 && BLOCK_SUPERBLOCK (bl) != 0) | |
52 | + while ((BLOCK_FUNCTION (bl) == NULL || block_inlined_p (bl)) | |
53 | + && BLOCK_SUPERBLOCK (bl) != NULL) | |
54 | bl = BLOCK_SUPERBLOCK (bl); | |
55 | ||
56 | return BLOCK_FUNCTION (bl); | |
57 | } | |
58 | ||
59 | +/* Return one if BL represents an inlined function. */ | |
60 | + | |
61 | +int | |
62 | +block_inlined_p (const struct block *bl) | |
63 | +{ | |
64 | + return BLOCK_FUNCTION (bl) != NULL && SYMBOL_INLINED (BLOCK_FUNCTION (bl)); | |
65 | +} | |
66 | + | |
67 | /* Return the blockvector immediately containing the innermost lexical | |
68 | block containing the specified pc value and section, or 0 if there | |
69 | is none. PBLOCK is a pointer to the block. If PBLOCK is NULL, we | |
d566d21e | 70 | Index: gdb-6.8.50.20090302/gdb/block.h |
3a58abaf | 71 | =================================================================== |
d566d21e | 72 | --- gdb-6.8.50.20090302.orig/gdb/block.h 2009-01-03 06:57:50.000000000 +0100 |
73 | +++ gdb-6.8.50.20090302/gdb/block.h 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
74 | @@ -65,7 +65,7 @@ struct block |
75 | CORE_ADDR endaddr; | |
76 | ||
77 | /* The symbol that names this block, if the block is the body of a | |
78 | - function; otherwise, zero. */ | |
79 | + function (real or inlined); otherwise, zero. */ | |
80 | ||
81 | struct symbol *function; | |
82 | ||
83 | @@ -134,6 +134,8 @@ enum { GLOBAL_BLOCK = 0, STATIC_BLOCK = | |
84 | ||
85 | extern struct symbol *block_linkage_function (const struct block *); | |
86 | ||
87 | +extern int block_inlined_p (const struct block *block); | |
88 | + | |
89 | extern int contained_in (const struct block *, const struct block *); | |
90 | ||
91 | extern struct blockvector *blockvector_for_pc (CORE_ADDR, struct block **); | |
d566d21e | 92 | Index: gdb-6.8.50.20090302/gdb/blockframe.c |
3a58abaf | 93 | =================================================================== |
d566d21e | 94 | --- gdb-6.8.50.20090302.orig/gdb/blockframe.c 2009-01-03 06:57:50.000000000 +0100 |
95 | +++ gdb-6.8.50.20090302/gdb/blockframe.c 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
96 | @@ -36,6 +36,7 @@ |
97 | #include "command.h" | |
98 | #include "gdbcmd.h" | |
99 | #include "block.h" | |
100 | +#include "inline-frame.h" | |
101 | ||
102 | /* Prototypes for exported functions. */ | |
103 | ||
104 | @@ -61,11 +62,29 @@ struct block * | |
105 | get_frame_block (struct frame_info *frame, CORE_ADDR *addr_in_block) | |
106 | { | |
107 | const CORE_ADDR pc = get_frame_address_in_block (frame); | |
108 | + struct frame_info *next_frame; | |
109 | + struct block *bl; | |
110 | + int inline_count; | |
111 | ||
112 | if (addr_in_block) | |
113 | *addr_in_block = pc; | |
114 | ||
115 | - return block_for_pc (pc); | |
116 | + bl = block_for_pc (pc); | |
117 | + if (bl == NULL) | |
118 | + return NULL; | |
119 | + | |
120 | + inline_count = frame_inlined_callees (frame); | |
121 | + | |
122 | + while (inline_count > 0) | |
123 | + { | |
124 | + if (block_inlined_p (bl)) | |
125 | + inline_count--; | |
126 | + | |
127 | + bl = BLOCK_SUPERBLOCK (bl); | |
128 | + gdb_assert (bl != NULL); | |
129 | + } | |
130 | + | |
131 | + return bl; | |
132 | } | |
133 | ||
134 | CORE_ADDR | |
135 | @@ -104,9 +123,14 @@ struct symbol * | |
136 | get_frame_function (struct frame_info *frame) | |
137 | { | |
138 | struct block *bl = get_frame_block (frame, 0); | |
139 | - if (bl == 0) | |
140 | - return 0; | |
141 | - return block_linkage_function (bl); | |
142 | + | |
143 | + if (bl == NULL) | |
144 | + return NULL; | |
145 | + | |
146 | + while (BLOCK_FUNCTION (bl) == NULL && BLOCK_SUPERBLOCK (bl) != NULL) | |
147 | + bl = BLOCK_SUPERBLOCK (bl); | |
148 | + | |
149 | + return BLOCK_FUNCTION (bl); | |
150 | } | |
151 | \f | |
152 | ||
153 | @@ -350,8 +374,8 @@ block_innermost_frame (struct block *blo | |
154 | frame = get_current_frame (); | |
155 | while (frame != NULL) | |
156 | { | |
157 | - calling_pc = get_frame_address_in_block (frame); | |
158 | - if (calling_pc >= start && calling_pc < end) | |
159 | + struct block *frame_block = get_frame_block (frame, NULL); | |
160 | + if (frame_block != NULL && contained_in (frame_block, block)) | |
161 | return frame; | |
162 | ||
163 | frame = get_prev_frame (frame); | |
d566d21e | 164 | Index: gdb-6.8.50.20090302/gdb/breakpoint.c |
3a58abaf | 165 | =================================================================== |
d566d21e | 166 | --- gdb-6.8.50.20090302.orig/gdb/breakpoint.c 2009-03-21 21:06:05.000000000 +0100 |
167 | +++ gdb-6.8.50.20090302/gdb/breakpoint.c 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
168 | @@ -2641,19 +2641,21 @@ watchpoint_check (void *p) |
169 | within_current_scope = 1; | |
170 | else | |
171 | { | |
172 | - /* There is no current frame at this moment. If we're going to have | |
173 | - any chance of handling watchpoints on local variables, we'll need | |
174 | - the frame chain (so we can determine if we're in scope). */ | |
175 | - reinit_frame_cache (); | |
176 | fr = frame_find_by_id (b->watchpoint_frame); | |
177 | within_current_scope = (fr != NULL); | |
178 | ||
179 | /* If we've gotten confused in the unwinder, we might have | |
180 | returned a frame that can't describe this variable. */ | |
181 | - if (within_current_scope | |
182 | - && (block_linkage_function (b->exp_valid_block) | |
183 | - != get_frame_function (fr))) | |
184 | - within_current_scope = 0; | |
185 | + if (within_current_scope) | |
186 | + { | |
187 | + struct symbol *function; | |
188 | + | |
189 | + function = get_frame_function (fr); | |
190 | + if (function == NULL | |
191 | + || !contained_in (b->exp_valid_block, | |
192 | + SYMBOL_BLOCK_VALUE (function))) | |
193 | + within_current_scope = 0; | |
194 | + } | |
195 | ||
196 | /* in_function_epilogue_p() returns a non-zero value if we're still | |
197 | in the function but the stack frame has already been invalidated. | |
198 | @@ -2665,10 +2667,9 @@ watchpoint_check (void *p) | |
199 | that the watchpoint frame couldn't be found by frame_find_by_id() | |
200 | because the current PC is currently in an epilogue. Calling | |
201 | gdbarch_in_function_epilogue_p() also when fr == NULL fixes that. */ | |
202 | - if ((!within_current_scope || fr == get_current_frame ()) | |
203 | - && gdbarch_in_function_epilogue_p (current_gdbarch, read_pc ())) | |
204 | + if (gdbarch_in_function_epilogue_p (current_gdbarch, read_pc ())) | |
205 | return WP_VALUE_NOT_CHANGED; | |
206 | - if (fr && within_current_scope) | |
207 | + if (within_current_scope) | |
208 | /* If we end up stopping, the current frame will get selected | |
209 | in normal_stop. So this call to select_frame won't affect | |
210 | the user. */ | |
211 | @@ -2902,7 +2903,7 @@ bpstat_check_breakpoint_conditions (bpst | |
212 | struct breakpoint *b = bl->owner; | |
213 | ||
214 | if (frame_id_p (b->frame_id) | |
215 | - && !frame_id_eq (b->frame_id, get_frame_id (get_current_frame ()))) | |
216 | + && !frame_id_eq (b->frame_id, get_stack_frame_id (get_current_frame ()))) | |
217 | bs->stop = 0; | |
218 | else if (bs->stop) | |
219 | { | |
220 | @@ -2917,8 +2918,12 @@ bpstat_check_breakpoint_conditions (bpst | |
221 | ||
222 | if (bl->cond && bl->owner->disposition != disp_del_at_next_stop) | |
223 | { | |
224 | - /* Need to select the frame, with all that implies | |
225 | - so that the conditions will have the right context. */ | |
226 | + /* Need to select the frame, with all that implies so that | |
227 | + the conditions will have the right context. Because we | |
228 | + use the frame, we will not see an inlined function's | |
229 | + variables when we arrive at a breakpoint at the start | |
230 | + of the inlined function; the current frame will be the | |
231 | + call site. */ | |
232 | select_frame (get_current_frame ()); | |
233 | value_is_zero | |
234 | = catch_errors (breakpoint_cond_eval, (bl->cond), | |
d566d21e | 235 | @@ -5163,6 +5168,11 @@ set_momentary_breakpoint (struct symtab_ |
3a58abaf AM |
236 | enum bptype type) |
237 | { | |
238 | struct breakpoint *b; | |
239 | + | |
240 | + /* If FRAME_ID is valid, it should be a real frame, not an inlined | |
241 | + one. */ | |
242 | + gdb_assert (!frame_id_inlined_p (frame_id)); | |
243 | + | |
244 | b = set_raw_breakpoint (sal, type); | |
245 | b->enable_state = bp_enabled; | |
246 | b->disposition = disp_donttouch; | |
d566d21e | 247 | @@ -6203,7 +6213,6 @@ watch_command_1 (char *arg, int accessfl |
3a58abaf AM |
248 | struct block *exp_valid_block; |
249 | struct value *val, *mark, *val_chain; | |
250 | struct frame_info *frame; | |
251 | - struct frame_info *prev_frame = NULL; | |
252 | char *exp_start = NULL; | |
253 | char *exp_end = NULL; | |
254 | char *tok, *id_tok_start, *end_tok; | |
d566d21e | 255 | @@ -6364,34 +6373,34 @@ watch_command_1 (char *arg, int accessfl |
3a58abaf AM |
256 | bp_type = bp_watchpoint; |
257 | ||
258 | frame = block_innermost_frame (exp_valid_block); | |
259 | - if (frame) | |
260 | - prev_frame = get_prev_frame (frame); | |
261 | - else | |
262 | - prev_frame = NULL; | |
263 | ||
264 | /* If the expression is "local", then set up a "watchpoint scope" | |
265 | breakpoint at the point where we've left the scope of the watchpoint | |
266 | expression. Create the scope breakpoint before the watchpoint, so | |
267 | that we will encounter it first in bpstat_stop_status. */ | |
268 | - if (innermost_block && prev_frame) | |
269 | + if (innermost_block && frame) | |
270 | { | |
271 | - scope_breakpoint = create_internal_breakpoint (get_frame_pc (prev_frame), | |
272 | - bp_watchpoint_scope); | |
273 | + if (frame_id_p (frame_unwind_id (frame))) | |
274 | + { | |
275 | + scope_breakpoint | |
276 | + = create_internal_breakpoint (frame_pc_unwind (frame), | |
277 | + bp_watchpoint_scope); | |
278 | ||
279 | - scope_breakpoint->enable_state = bp_enabled; | |
280 | + scope_breakpoint->enable_state = bp_enabled; | |
281 | ||
282 | - /* Automatically delete the breakpoint when it hits. */ | |
283 | - scope_breakpoint->disposition = disp_del; | |
284 | + /* Automatically delete the breakpoint when it hits. */ | |
285 | + scope_breakpoint->disposition = disp_del; | |
286 | ||
287 | - /* Only break in the proper frame (help with recursion). */ | |
288 | - scope_breakpoint->frame_id = get_frame_id (prev_frame); | |
289 | + /* Only break in the proper frame (help with recursion). */ | |
290 | + scope_breakpoint->frame_id = frame_unwind_id (frame); | |
291 | ||
292 | - /* Set the address at which we will stop. */ | |
293 | - scope_breakpoint->loc->requested_address | |
294 | - = get_frame_pc (prev_frame); | |
295 | - scope_breakpoint->loc->address | |
296 | - = adjust_breakpoint_address (scope_breakpoint->loc->requested_address, | |
297 | - scope_breakpoint->type); | |
298 | + /* Set the address at which we will stop. */ | |
299 | + scope_breakpoint->loc->requested_address | |
300 | + = frame_pc_unwind (frame); | |
301 | + scope_breakpoint->loc->address | |
302 | + = adjust_breakpoint_address (scope_breakpoint->loc->requested_address, | |
303 | + scope_breakpoint->type); | |
304 | + } | |
305 | } | |
306 | ||
307 | /* Now set up the breakpoint. */ | |
d566d21e | 308 | @@ -6572,7 +6581,6 @@ until_break_command (char *arg, int from |
3a58abaf AM |
309 | struct symtabs_and_lines sals; |
310 | struct symtab_and_line sal; | |
311 | struct frame_info *frame = get_selected_frame (NULL); | |
312 | - struct frame_info *prev_frame = get_prev_frame (frame); | |
313 | struct breakpoint *breakpoint; | |
314 | struct breakpoint *breakpoint2 = NULL; | |
315 | struct cleanup *old_chain; | |
d566d21e | 316 | @@ -6605,20 +6613,22 @@ until_break_command (char *arg, int from |
3a58abaf AM |
317 | we don't specify a frame at which we need to stop. */ |
318 | breakpoint = set_momentary_breakpoint (sal, null_frame_id, bp_until); | |
319 | else | |
320 | - /* Otherwise, specify the current frame, because we want to stop only | |
321 | + /* Otherwise, specify the selected frame, because we want to stop only | |
322 | at the very same frame. */ | |
323 | - breakpoint = set_momentary_breakpoint (sal, get_frame_id (frame), | |
324 | + breakpoint = set_momentary_breakpoint (sal, get_stack_frame_id (frame), | |
325 | bp_until); | |
326 | ||
327 | old_chain = make_cleanup_delete_breakpoint (breakpoint); | |
328 | ||
329 | /* Keep within the current frame, or in frames called by the current | |
330 | one. */ | |
331 | - if (prev_frame) | |
332 | + | |
333 | + if (frame_id_p (frame_unwind_id (frame))) | |
334 | { | |
335 | - sal = find_pc_line (get_frame_pc (prev_frame), 0); | |
336 | - sal.pc = get_frame_pc (prev_frame); | |
337 | - breakpoint2 = set_momentary_breakpoint (sal, get_frame_id (prev_frame), | |
338 | + sal = find_pc_line (frame_pc_unwind (frame), 0); | |
339 | + sal.pc = frame_pc_unwind (frame); | |
340 | + breakpoint2 = set_momentary_breakpoint (sal, | |
341 | + frame_unwind_id (frame), | |
342 | bp_until); | |
343 | make_cleanup_delete_breakpoint (breakpoint2); | |
344 | } | |
d566d21e | 345 | Index: gdb-6.8.50.20090302/gdb/buildsym.c |
3a58abaf | 346 | =================================================================== |
d566d21e | 347 | --- gdb-6.8.50.20090302.orig/gdb/buildsym.c 2009-03-21 21:06:02.000000000 +0100 |
348 | +++ gdb-6.8.50.20090302/gdb/buildsym.c 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
349 | @@ -1155,6 +1155,12 @@ end_symtab (CORE_ADDR end_addr, struct o |
350 | struct symbol *sym; | |
351 | struct dict_iterator iter; | |
352 | ||
353 | + /* Inlined functions may have symbols not in the global or static | |
354 | + symbol lists. */ | |
355 | + if (BLOCK_FUNCTION (block) != NULL) | |
356 | + if (SYMBOL_SYMTAB (BLOCK_FUNCTION (block)) == NULL) | |
357 | + SYMBOL_SYMTAB (BLOCK_FUNCTION (block)) = symtab; | |
358 | + | |
359 | for (sym = dict_iterator_first (BLOCK_DICT (block), &iter); | |
360 | sym != NULL; | |
361 | sym = dict_iterator_next (&iter)) | |
d566d21e | 362 | Index: gdb-6.8.50.20090302/gdb/doc/gdb.texinfo |
3a58abaf | 363 | =================================================================== |
d566d21e | 364 | --- gdb-6.8.50.20090302.orig/gdb/doc/gdb.texinfo 2009-03-21 21:06:05.000000000 +0100 |
365 | +++ gdb-6.8.50.20090302/gdb/doc/gdb.texinfo 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
366 | @@ -137,6 +137,7 @@ software in general. We will miss him. |
367 | * Stack:: Examining the stack | |
368 | * Source:: Examining source files | |
369 | * Data:: Examining data | |
370 | +* Optimized Code:: Debugging optimized code | |
371 | * Macros:: Preprocessor Macros | |
372 | * Tracepoints:: Debugging remote targets non-intrusively | |
373 | * Overlays:: Debugging programs that use overlays | |
374 | @@ -1824,7 +1825,7 @@ To request debugging information, specif | |
375 | the compiler. | |
376 | ||
377 | Programs that are to be shipped to your customers are compiled with | |
378 | -optimizations, using the @samp{-O} compiler option. However, many | |
379 | +optimizations, using the @samp{-O} compiler option. However, some | |
380 | compilers are unable to handle the @samp{-g} and @samp{-O} options | |
381 | together. Using those compilers, you cannot generate optimized | |
382 | executables containing debugging information. | |
383 | @@ -1833,22 +1834,7 @@ executables containing debugging informa | |
384 | without @samp{-O}, making it possible to debug optimized code. We | |
385 | recommend that you @emph{always} use @samp{-g} whenever you compile a | |
386 | program. You may think your program is correct, but there is no sense | |
387 | -in pushing your luck. | |
388 | - | |
389 | -@cindex optimized code, debugging | |
390 | -@cindex debugging optimized code | |
391 | -When you debug a program compiled with @samp{-g -O}, remember that the | |
392 | -optimizer is rearranging your code; the debugger shows you what is | |
393 | -really there. Do not be too surprised when the execution path does not | |
394 | -exactly match your source file! An extreme example: if you define a | |
395 | -variable, but never use it, @value{GDBN} never sees that | |
396 | -variable---because the compiler optimizes it out of existence. | |
397 | - | |
398 | -Some things do not work as well with @samp{-g -O} as with just | |
399 | -@samp{-g}, particularly on machines with instruction scheduling. If in | |
400 | -doubt, recompile with @samp{-g} alone, and if this fixes the problem, | |
401 | -please report it to us as a bug (including a test case!). | |
402 | -@xref{Variables}, for more information about debugging optimized code. | |
403 | +in pushing your luck. For more information, see @ref{Optimized Code}. | |
404 | ||
405 | Older versions of the @sc{gnu} C compiler permitted a variant option | |
406 | @w{@samp{-gg}} for debugging information. @value{GDBN} no longer supports this | |
d566d21e | 407 | @@ -8406,6 +8392,107 @@ $1 = 1 |
3a58abaf AM |
408 | $2 = (void *) 0x8049560 |
409 | @end smallexample | |
410 | ||
411 | +@node Optimized Code | |
412 | +@chapter Debugging Optimized Code | |
413 | +@cindex optimized code, debugging | |
414 | +@cindex debugging optimized code | |
415 | + | |
416 | +Almost all compilers support optimization. With optimization | |
417 | +disabled, the compiler generates assembly code that corresponds | |
418 | +directly to your source code, in a simplistic way. As the compiler | |
419 | +applies more powerful optimizations, the generated assembly code | |
420 | +diverges from your original source code. With help from debugging | |
421 | +information generated by the compiler, @value{GDBN} can map from | |
422 | +the running program back to constructs from your original source. | |
423 | + | |
424 | +@value{GDBN} is more accurate with optimization disabled. If you | |
425 | +can recompile without optimization, it is easier to follow the | |
426 | +progress of your program during debugging. But, there are many cases | |
427 | +where you may need to debug an optimized version. | |
428 | + | |
429 | +When you debug a program compiled with @samp{-g -O}, remember that the | |
430 | +optimizer has rearranged your code; the debugger shows you what is | |
431 | +really there. Do not be too surprised when the execution path does not | |
432 | +exactly match your source file! An extreme example: if you define a | |
433 | +variable, but never use it, @value{GDBN} never sees that | |
434 | +variable---because the compiler optimizes it out of existence. | |
435 | + | |
436 | +Some things do not work as well with @samp{-g -O} as with just | |
437 | +@samp{-g}, particularly on machines with instruction scheduling. If in | |
438 | +doubt, recompile with @samp{-g} alone, and if this fixes the problem, | |
439 | +please report it to us as a bug (including a test case!). | |
440 | +@xref{Variables}, for more information about debugging optimized code. | |
441 | + | |
442 | +@menu | |
443 | +* Inline Functions:: How @value{GDBN} presents inlining | |
444 | +@end menu | |
445 | + | |
446 | +@node Inline Functions | |
447 | +@section Inline Functions | |
448 | +@cindex inline functions, debugging | |
449 | + | |
450 | +@dfn{Inlining} is an optimization that inserts a copy of the function | |
451 | +body directly at each call site, instead of jumping to a shared | |
452 | +routine. @value{GDBN} displays inlined functions just like | |
453 | +non-inlined functions. They appear in backtraces. You can view their | |
454 | +arguments and local variables, step into them with @code{step}, skip | |
455 | +them with @code{next}, and escape from them with @code{finish}. | |
456 | +You can check whether a function was inlined by using the | |
457 | +@code{info frame} command. | |
458 | + | |
459 | +For @value{GDBN} to support inlined functions, the compiler must | |
460 | +record information about inlining in the debug information --- | |
461 | +@value{NGCC} using the @sc{dwarf 2} format does this, and several | |
462 | +other compilers do also. @value{GDBN} only supports inlined functions | |
463 | +when using @sc{dwarf 2}. Versions of @value{NGCC} before 4.1 | |
464 | +do not emit two required attributes (@samp{DW_AT_call_file} and | |
465 | +@samp{DW_AT_call_line}); @value{GDBN} does not display inlined | |
466 | +function calls with earlier versions of @value{NGCC}. It instead | |
467 | +displays the arguments and local variables of inlined functions as | |
468 | +local variables in the caller. | |
469 | + | |
470 | +The body of an inlined function is directly included at its call site; | |
471 | +unlike a non-inlined function, there are no instructions devoted to | |
472 | +the call. @value{GDBN} still pretends that the call site and the | |
473 | +start of the inlined function are different instructions. Stepping to | |
474 | +the call site shows the call site, and then stepping again shows | |
475 | +the first line of the inlined function, even though no additional | |
476 | +instructions are executed. | |
477 | + | |
478 | +This makes source-level debugging much clearer; you can see both the | |
479 | +context of the call and then the effect of the call. Only stepping by | |
480 | +a single instruction using @code{stepi} or @code{nexti} does not do | |
481 | +this; single instruction steps always show the inlined body. | |
482 | + | |
483 | +There are some ways that @value{GDBN} does not pretend that inlined | |
484 | +function calls are the same as normal calls: | |
485 | + | |
486 | +@itemize @bullet | |
487 | +@item | |
488 | +You cannot set breakpoints on inlined functions. @value{GDBN} | |
489 | +either reports that there is no symbol with that name, or else sets the | |
490 | +breakpoint only on non-inlined copies of the function. This limitation | |
491 | +will be removed in a future version of @value{GDBN}; until then, | |
492 | +set a breakpoint by line number on the first line of the inlined | |
493 | +function instead. | |
494 | + | |
495 | +@item | |
496 | +Setting breakpoints at the call site of an inlined function may not | |
497 | +work, because the call site does not contain any code. @value{GDBN} | |
498 | +may incorrectly move the breakpoint to the next line of the enclosing | |
499 | +function, after the call. This limitation will be removed in a future | |
500 | +version of @value{GDBN}; until then, set a breakpoint on an earlier line | |
501 | +or inside the inlined function instead. | |
502 | + | |
503 | +@item | |
504 | +@value{GDBN} cannot locate the return value of inlined calls after | |
505 | +using the @code{finish} command. This is a limitation of compiler-generated | |
506 | +debugging information; after @code{finish}, you can step to the next line | |
507 | +and print a variable where your program stored the return value. | |
508 | + | |
509 | +@end itemize | |
510 | + | |
511 | + | |
512 | @node Macros | |
513 | @chapter C Preprocessor Macros | |
514 | ||
d566d21e | 515 | Index: gdb-6.8.50.20090302/gdb/dwarf2loc.c |
3a58abaf | 516 | =================================================================== |
d566d21e | 517 | --- gdb-6.8.50.20090302.orig/gdb/dwarf2loc.c 2009-03-21 21:06:02.000000000 +0100 |
518 | +++ gdb-6.8.50.20090302/gdb/dwarf2loc.c 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
519 | @@ -31,6 +31,7 @@ |
520 | #include "regcache.h" | |
521 | #include "objfiles.h" | |
522 | #include "exceptions.h" | |
523 | +#include "block.h" | |
524 | ||
525 | #include "elf/dwarf2.h" | |
526 | #include "dwarf2expr.h" | |
527 | @@ -150,7 +151,10 @@ dwarf_expr_frame_base (void *baton, gdb_ | |
528 | struct symbol *framefunc; | |
529 | struct dwarf_expr_baton *debaton = (struct dwarf_expr_baton *) baton; | |
530 | ||
531 | - framefunc = get_frame_function (debaton->frame); | |
532 | + /* Use block_linkage_function, which returns a real (not inlined) | |
533 | + function, instead of get_frame_function, which may return an | |
534 | + inlined function. */ | |
535 | + framefunc = block_linkage_function (get_frame_block (debaton->frame, NULL)); | |
536 | ||
537 | /* If we found a frame-relative symbol then it was certainly within | |
538 | some function associated with a frame. If we can't find the frame, | |
d566d21e | 539 | Index: gdb-6.8.50.20090302/gdb/dwarf2read.c |
3a58abaf | 540 | =================================================================== |
d566d21e | 541 | --- gdb-6.8.50.20090302.orig/gdb/dwarf2read.c 2009-03-21 21:06:04.000000000 +0100 |
542 | +++ gdb-6.8.50.20090302/gdb/dwarf2read.c 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
543 | @@ -50,6 +50,7 @@ |
544 | #include "c-lang.h" | |
545 | #include "typeprint.h" | |
546 | #include "top.h" | |
547 | +#include "block.h" | |
548 | ||
549 | #include <fcntl.h> | |
550 | #include "gdb_string.h" | |
551 | @@ -2984,12 +2985,8 @@ process_die (struct die_info *die, struc | |
552 | read_file_scope (die, cu); | |
553 | break; | |
554 | case DW_TAG_subprogram: | |
555 | - read_func_scope (die, cu); | |
556 | - break; | |
557 | case DW_TAG_inlined_subroutine: | |
558 | - /* FIXME: These are ignored for now. | |
559 | - They could be used to set breakpoints on all inlined instances | |
560 | - of a function and make GDB `next' properly over inlined functions. */ | |
561 | + read_func_scope (die, cu); | |
562 | break; | |
563 | case DW_TAG_lexical_block: | |
564 | case DW_TAG_try_block: | |
565 | @@ -3464,6 +3461,22 @@ read_func_scope (struct die_info *die, s | |
566 | CORE_ADDR baseaddr; | |
567 | struct block *block; | |
568 | unsigned die_children = 0; | |
569 | + struct attribute *call_line, *call_file; | |
570 | + int inlined_func = (die->tag == DW_TAG_inlined_subroutine); | |
571 | + | |
572 | + if (inlined_func) | |
573 | + { | |
574 | + /* If we do not have call site information, we can't show the | |
575 | + caller of this inlined function. That's too confusing, so | |
576 | + only use the scope for local variables. */ | |
577 | + call_line = dwarf2_attr (die, DW_AT_call_line, cu); | |
578 | + call_file = dwarf2_attr (die, DW_AT_call_file, cu); | |
579 | + if (call_line == NULL || call_file == NULL) | |
580 | + { | |
581 | + read_lexical_block_scope (die, cu); | |
582 | + return; | |
583 | + } | |
584 | + } | |
585 | ||
586 | baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); | |
587 | ||
d566d21e | 588 | @@ -7524,6 +7537,9 @@ die_specification (struct die_info *die, |
3a58abaf AM |
589 | *spec_cu); |
590 | ||
591 | if (spec_attr == NULL) | |
592 | + spec_attr = dwarf2_attr (die, DW_AT_abstract_origin, *spec_cu); | |
593 | + | |
594 | + if (spec_attr == NULL) | |
595 | return NULL; | |
596 | else | |
597 | return follow_die_ref (die, spec_attr, spec_cu); | |
d566d21e | 598 | @@ -8207,6 +8223,7 @@ new_symbol (struct die_info *die, struct |
3a58abaf AM |
599 | struct attribute *attr = NULL; |
600 | struct attribute *attr2 = NULL; | |
601 | CORE_ADDR baseaddr; | |
602 | + int inlined_func = (die->tag == DW_TAG_inlined_subroutine); | |
603 | ||
604 | baseaddr = ANOFFSET (objfile->section_offsets, SECT_OFF_TEXT (objfile)); | |
605 | ||
d566d21e | 606 | @@ -8257,13 +8274,17 @@ new_symbol (struct die_info *die, struct |
3a58abaf AM |
607 | SYMBOL_TYPE (sym) = type; |
608 | else | |
609 | SYMBOL_TYPE (sym) = die_type (die, cu); | |
610 | - attr = dwarf2_attr (die, DW_AT_decl_line, cu); | |
611 | + attr = dwarf2_attr (die, | |
612 | + inlined_func ? DW_AT_call_line : DW_AT_decl_line, | |
613 | + cu); | |
614 | if (attr) | |
615 | { | |
616 | SYMBOL_LINE (sym) = DW_UNSND (attr); | |
617 | } | |
618 | ||
619 | - attr = dwarf2_attr (die, DW_AT_decl_file, cu); | |
620 | + attr = dwarf2_attr (die, | |
621 | + inlined_func ? DW_AT_call_file : DW_AT_decl_file, | |
622 | + cu); | |
623 | if (attr) | |
624 | { | |
625 | int file_index = DW_UNSND (attr); | |
d566d21e | 626 | @@ -8310,6 +8331,14 @@ new_symbol (struct die_info *die, struct |
3a58abaf AM |
627 | add_symbol_to_list (sym, cu->list_in_scope); |
628 | } | |
629 | break; | |
630 | + case DW_TAG_inlined_subroutine: | |
631 | + /* SYMBOL_BLOCK_VALUE (sym) will be filled in later by | |
632 | + finish_block. */ | |
633 | + SYMBOL_CLASS (sym) = LOC_BLOCK; | |
634 | + SYMBOL_INLINED (sym) = 1; | |
635 | + /* Do not add the symbol to any lists. It will be found via | |
636 | + BLOCK_FUNCTION from the blockvector. */ | |
637 | + break; | |
638 | case DW_TAG_variable: | |
639 | /* Compilation with minimal debug info may result in variables | |
640 | with missing type entries. Change the misleading `void' type | |
d566d21e | 641 | @@ -8365,7 +8394,14 @@ new_symbol (struct die_info *die, struct |
3a58abaf AM |
642 | } |
643 | break; | |
644 | case DW_TAG_formal_parameter: | |
645 | - SYMBOL_IS_ARGUMENT (sym) = 1; | |
646 | + /* If we are inside a function, mark this as an argument. If | |
647 | + not, we might be looking at an argument to an inlined function | |
648 | + when we do not have enough information to show inlined frames; | |
649 | + pretend it's a local variable in that case so that the user can | |
650 | + still see it. */ | |
651 | + if (context_stack_depth > 0 | |
652 | + && context_stack[context_stack_depth - 1].name != NULL) | |
653 | + SYMBOL_IS_ARGUMENT (sym) = 1; | |
654 | attr = dwarf2_attr (die, DW_AT_location, cu); | |
655 | if (attr) | |
656 | { | |
d566d21e | 657 | Index: gdb-6.8.50.20090302/gdb/frame-unwind.c |
3a58abaf | 658 | =================================================================== |
d566d21e | 659 | --- gdb-6.8.50.20090302.orig/gdb/frame-unwind.c 2009-01-03 06:57:51.000000000 +0100 |
660 | +++ gdb-6.8.50.20090302/gdb/frame-unwind.c 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
661 | @@ -21,6 +21,7 @@ |
662 | #include "frame.h" | |
663 | #include "frame-unwind.h" | |
664 | #include "dummy-frame.h" | |
665 | +#include "inline-frame.h" | |
666 | #include "value.h" | |
667 | #include "regcache.h" | |
668 | ||
669 | @@ -51,8 +52,10 @@ frame_unwind_init (struct obstack *obsta | |
670 | can't override this. */ | |
671 | table->list = OBSTACK_ZALLOC (obstack, struct frame_unwind_table_entry); | |
672 | table->list->unwinder = dummy_frame_unwind; | |
673 | + table->list->next = OBSTACK_ZALLOC (obstack, struct frame_unwind_table_entry); | |
674 | + table->list->next->unwinder = inline_frame_unwind; | |
675 | /* The insertion point for OSABI sniffers. */ | |
676 | - table->osabi_head = &table->list->next; | |
677 | + table->osabi_head = &table->list->next->next; | |
678 | return table; | |
679 | } | |
680 | ||
d566d21e | 681 | Index: gdb-6.8.50.20090302/gdb/frame.c |
3a58abaf | 682 | =================================================================== |
d566d21e | 683 | --- gdb-6.8.50.20090302.orig/gdb/frame.c 2009-03-21 21:06:03.000000000 +0100 |
684 | +++ gdb-6.8.50.20090302/gdb/frame.c 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
685 | @@ -41,8 +41,14 @@ |
686 | #include "objfiles.h" | |
687 | #include "exceptions.h" | |
688 | #include "gdbthread.h" | |
689 | +#include "block.h" | |
690 | +#include "inline-frame.h" | |
691 | ||
692 | static struct frame_info *get_prev_frame_1 (struct frame_info *this_frame); | |
693 | +static struct frame_info *get_prev_frame_raw (struct frame_info *this_frame); | |
694 | + | |
695 | +static void deprecated_update_frame_pc_hack (struct frame_info *frame, | |
696 | + CORE_ADDR pc); | |
697 | ||
698 | /* We keep a cache of stack frames, each of which is a "struct | |
699 | frame_info". The innermost one gets allocated (in | |
700 | @@ -183,6 +189,8 @@ fprint_frame_id (struct ui_file *file, s | |
701 | fprint_field (file, "code", id.code_addr_p, id.code_addr); | |
702 | fprintf_unfiltered (file, ","); | |
703 | fprint_field (file, "special", id.special_addr_p, id.special_addr); | |
704 | + if (id.inline_depth) | |
705 | + fprintf_unfiltered (file, ",inlined=%d", id.inline_depth); | |
706 | fprintf_unfiltered (file, "}"); | |
707 | } | |
708 | ||
709 | @@ -197,6 +205,12 @@ fprint_frame_type (struct ui_file *file, | |
710 | case DUMMY_FRAME: | |
711 | fprintf_unfiltered (file, "DUMMY_FRAME"); | |
712 | return; | |
713 | + case INLINE_FRAME: | |
714 | + fprintf_unfiltered (file, "INLINE_FRAME"); | |
715 | + return; | |
716 | + case SENTINEL_FRAME: | |
717 | + fprintf_unfiltered (file, "SENTINEL_FRAME"); | |
718 | + return; | |
719 | case SIGTRAMP_FRAME: | |
720 | fprintf_unfiltered (file, "SIGTRAMP_FRAME"); | |
721 | return; | |
722 | @@ -249,6 +263,18 @@ fprint_frame (struct ui_file *file, stru | |
723 | fprintf_unfiltered (file, "}"); | |
724 | } | |
725 | ||
726 | +/* Given FRAME, return the enclosing normal frame for inlined | |
727 | + function frames. Otherwise return the original frame. */ | |
728 | + | |
729 | +static struct frame_info * | |
730 | +skip_inlined_frames (struct frame_info *frame) | |
731 | +{ | |
732 | + while (get_frame_type (frame) == INLINE_FRAME) | |
733 | + frame = get_prev_frame (frame); | |
734 | + | |
735 | + return frame; | |
736 | +} | |
737 | + | |
738 | /* Return a frame uniq ID that can be used to, later, re-find the | |
739 | frame. */ | |
740 | ||
741 | @@ -281,13 +307,21 @@ get_frame_id (struct frame_info *fi) | |
742 | } | |
743 | ||
744 | struct frame_id | |
745 | +get_stack_frame_id (struct frame_info *next_frame) | |
746 | +{ | |
747 | + return get_frame_id (skip_inlined_frames (next_frame)); | |
748 | +} | |
749 | + | |
750 | +struct frame_id | |
751 | frame_unwind_id (struct frame_info *next_frame) | |
752 | { | |
753 | /* Use prev_frame, and not get_prev_frame. The latter will truncate | |
754 | the frame chain, leading to this function unintentionally | |
755 | returning a null_frame_id (e.g., when a caller requests the frame | |
756 | ID of "main()"s caller. */ | |
757 | - return get_frame_id (get_prev_frame_1 (next_frame)); | |
758 | + | |
759 | + next_frame = skip_inlined_frames (next_frame); | |
760 | + return get_frame_id (skip_inlined_frames (get_prev_frame_1 (next_frame))); | |
761 | } | |
762 | ||
763 | const struct frame_id null_frame_id; /* All zeros. */ | |
764 | @@ -342,6 +376,15 @@ frame_id_p (struct frame_id l) | |
765 | } | |
766 | ||
767 | int | |
768 | +frame_id_inlined_p (struct frame_id l) | |
769 | +{ | |
770 | + if (!frame_id_p (l)) | |
771 | + return 0; | |
772 | + | |
773 | + return (l.inline_depth != 0); | |
774 | +} | |
775 | + | |
776 | +int | |
777 | frame_id_eq (struct frame_id l, struct frame_id r) | |
778 | { | |
779 | int eq; | |
780 | @@ -352,21 +395,22 @@ frame_id_eq (struct frame_id l, struct f | |
781 | else if (l.stack_addr != r.stack_addr) | |
782 | /* If .stack addresses are different, the frames are different. */ | |
783 | eq = 0; | |
784 | - else if (!l.code_addr_p || !r.code_addr_p) | |
785 | - /* An invalid code addr is a wild card, always succeed. */ | |
786 | - eq = 1; | |
787 | - else if (l.code_addr != r.code_addr) | |
788 | - /* If .code addresses are different, the frames are different. */ | |
789 | + else if (l.code_addr_p && r.code_addr_p && l.code_addr != r.code_addr) | |
790 | + /* An invalid code addr is a wild card. If .code addresses are | |
791 | + different, the frames are different. */ | |
792 | eq = 0; | |
793 | - else if (!l.special_addr_p || !r.special_addr_p) | |
794 | - /* An invalid special addr is a wild card (or unused), always succeed. */ | |
795 | - eq = 1; | |
796 | - else if (l.special_addr == r.special_addr) | |
797 | + else if (l.special_addr_p && r.special_addr_p | |
798 | + && l.special_addr != r.special_addr) | |
799 | + /* An invalid special addr is a wild card (or unused). Otherwise | |
800 | + if special addresses are different, the frames are different. */ | |
801 | + eq = 0; | |
802 | + else if (l.inline_depth != r.inline_depth) | |
803 | + /* If inline depths are different, the frames must be different. */ | |
804 | + eq = 0; | |
805 | + else | |
806 | /* Frames are equal. */ | |
807 | eq = 1; | |
808 | - else | |
809 | - /* No luck. */ | |
810 | - eq = 0; | |
811 | + | |
812 | if (frame_debug) | |
813 | { | |
814 | fprintf_unfiltered (gdb_stdlog, "{ frame_id_eq (l="); | |
815 | @@ -411,6 +455,29 @@ frame_id_inner (struct gdbarch *gdbarch, | |
816 | if (!l.stack_addr_p || !r.stack_addr_p) | |
817 | /* Like NaN, any operation involving an invalid ID always fails. */ | |
818 | inner = 0; | |
819 | + else if (l.inline_depth > r.inline_depth | |
820 | + && l.stack_addr == r.stack_addr | |
821 | + && l.code_addr_p == r.code_addr_p | |
822 | + && l.special_addr_p == r.special_addr_p | |
823 | + && l.special_addr == r.special_addr) | |
824 | + { | |
825 | + /* Same function, different inlined functions. */ | |
826 | + struct block *lb, *rb; | |
827 | + | |
828 | + gdb_assert (l.code_addr_p && r.code_addr_p); | |
829 | + | |
830 | + lb = block_for_pc (l.code_addr); | |
831 | + rb = block_for_pc (r.code_addr); | |
832 | + | |
833 | + if (lb == NULL || rb == NULL) | |
834 | + /* Something's gone wrong. */ | |
835 | + inner = 0; | |
836 | + else | |
837 | + /* This will return true if LB and RB are the same block, or | |
838 | + if the block with the smaller depth lexically encloses the | |
839 | + block with the greater depth. */ | |
840 | + inner = contained_in (lb, rb); | |
841 | + } | |
842 | else | |
843 | /* Only return non-zero when strictly inner than. Note that, per | |
844 | comment in "frame.h", there is some fuzz here. Frameless | |
845 | @@ -463,8 +530,8 @@ frame_find_by_id (struct frame_id id) | |
846 | return NULL; | |
847 | } | |
848 | ||
849 | -CORE_ADDR | |
850 | -frame_pc_unwind (struct frame_info *this_frame) | |
851 | +static CORE_ADDR | |
852 | +frame_unwind_pc (struct frame_info *this_frame) | |
853 | { | |
854 | if (!this_frame->prev_pc.p) | |
855 | { | |
856 | @@ -503,6 +570,12 @@ frame_pc_unwind (struct frame_info *this | |
857 | } | |
858 | ||
859 | CORE_ADDR | |
860 | +frame_pc_unwind (struct frame_info *this_frame) | |
861 | +{ | |
862 | + return frame_unwind_pc (skip_inlined_frames (this_frame)); | |
863 | +} | |
864 | + | |
865 | +CORE_ADDR | |
866 | get_frame_func (struct frame_info *this_frame) | |
867 | { | |
868 | struct frame_info *next_frame = this_frame->next; | |
869 | @@ -1226,7 +1299,6 @@ frame_register_unwind_location (struct f | |
870 | static struct frame_info * | |
871 | get_prev_frame_1 (struct frame_info *this_frame) | |
872 | { | |
873 | - struct frame_info *prev_frame; | |
874 | struct frame_id this_id; | |
875 | struct gdbarch *gdbarch; | |
876 | ||
877 | @@ -1266,6 +1338,14 @@ get_prev_frame_1 (struct frame_info *thi | |
878 | this_frame->prev_p = 1; | |
879 | this_frame->stop_reason = UNWIND_NO_REASON; | |
880 | ||
881 | + /* If we are unwinding from an inline frame, all of the below tests | |
882 | + were already performed when we unwound from the next non-inline | |
883 | + frame. We must skip them, since we can not get THIS_FRAME's ID | |
884 | + until we have unwound all the way down to the previous non-inline | |
885 | + frame. */ | |
886 | + if (get_frame_type (this_frame) == INLINE_FRAME) | |
887 | + return get_prev_frame_raw (this_frame); | |
888 | + | |
889 | /* Check that this frame's ID was valid. If it wasn't, don't try to | |
890 | unwind to the prev frame. Be careful to not apply this test to | |
891 | the sentinel frame. */ | |
892 | @@ -1333,7 +1413,8 @@ get_prev_frame_1 (struct frame_info *thi | |
893 | if (this_frame->level > 0 | |
894 | && gdbarch_pc_regnum (gdbarch) >= 0 | |
895 | && get_frame_type (this_frame) == NORMAL_FRAME | |
896 | - && get_frame_type (this_frame->next) == NORMAL_FRAME) | |
897 | + && (get_frame_type (this_frame->next) == NORMAL_FRAME | |
898 | + || get_frame_type (this_frame->next) == INLINE_FRAME)) | |
899 | { | |
900 | int optimized, realnum, nrealnum; | |
901 | enum lval_type lval, nlval; | |
902 | @@ -1362,6 +1443,17 @@ get_prev_frame_1 (struct frame_info *thi | |
903 | } | |
904 | } | |
905 | ||
906 | + return get_prev_frame_raw (this_frame); | |
907 | +} | |
908 | + | |
909 | +/* Construct a new "struct frame_info" and link it previous to | |
910 | + this_frame. */ | |
911 | + | |
912 | +static struct frame_info * | |
913 | +get_prev_frame_raw (struct frame_info *this_frame) | |
914 | +{ | |
915 | + struct frame_info *prev_frame; | |
916 | + | |
917 | /* Allocate the new frame but do not wire it in to the frame chain. | |
918 | Some (bad) code in INIT_FRAME_EXTRA_INFO tries to look along | |
919 | frame->next to pull some fancy tricks (of course such code is, by | |
920 | @@ -1484,7 +1576,7 @@ get_prev_frame (struct frame_info *this_ | |
921 | the main function when we created the dummy frame, the dummy frame will | |
922 | point inside the main function. */ | |
923 | if (this_frame->level >= 0 | |
924 | - && get_frame_type (this_frame) != DUMMY_FRAME | |
925 | + && get_frame_type (this_frame) == NORMAL_FRAME | |
926 | && !backtrace_past_main | |
927 | && inside_main_func (this_frame)) | |
928 | /* Don't unwind past main(). Note, this is done _before_ the | |
929 | @@ -1529,8 +1621,9 @@ get_prev_frame (struct frame_info *this_ | |
930 | from main returns directly to the caller of main. Since we don't | |
931 | stop at main, we should at least stop at the entry point of the | |
932 | application. */ | |
933 | - if (!backtrace_past_entry | |
934 | - && get_frame_type (this_frame) != DUMMY_FRAME && this_frame->level >= 0 | |
935 | + if (this_frame->level >= 0 | |
936 | + && get_frame_type (this_frame) == NORMAL_FRAME | |
937 | + && !backtrace_past_entry | |
938 | && inside_entry_func (this_frame)) | |
939 | { | |
940 | frame_debug_got_null_frame (this_frame, "inside entry func"); | |
941 | @@ -1541,7 +1634,8 @@ get_prev_frame (struct frame_info *this_ | |
942 | like a SIGSEGV or a dummy frame, and hence that NORMAL frames | |
943 | will never unwind a zero PC. */ | |
944 | if (this_frame->level > 0 | |
945 | - && get_frame_type (this_frame) == NORMAL_FRAME | |
946 | + && (get_frame_type (this_frame) == NORMAL_FRAME | |
947 | + || get_frame_type (this_frame) == INLINE_FRAME) | |
948 | && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME | |
949 | && get_frame_pc (this_frame) == 0) | |
950 | { | |
951 | @@ -1566,7 +1660,7 @@ CORE_ADDR | |
952 | get_frame_pc (struct frame_info *frame) | |
953 | { | |
954 | gdb_assert (frame->next != NULL); | |
955 | - return frame_pc_unwind (frame->next); | |
956 | + return frame_unwind_pc (frame->next); | |
957 | } | |
958 | ||
959 | /* Return an address that falls within THIS_FRAME's code block. */ | |
960 | @@ -1611,17 +1705,58 @@ get_frame_address_in_block (struct frame | |
961 | We check the type of NEXT_FRAME first, since it is already | |
962 | known; frame type is determined by the unwinder, and since | |
963 | we have THIS_FRAME we've already selected an unwinder for | |
964 | - NEXT_FRAME. */ | |
965 | + NEXT_FRAME. | |
966 | + | |
967 | + If the next frame is inlined, we need to keep going until we find | |
968 | + the real function - for instance, if a signal handler is invoked | |
969 | + while in an inlined function, then the code address of the | |
970 | + "calling" normal function should not be adjusted either. */ | |
971 | + | |
972 | + while (get_frame_type (next_frame) == INLINE_FRAME) | |
973 | + next_frame = next_frame->next; | |
974 | + | |
975 | if (get_frame_type (next_frame) == NORMAL_FRAME | |
976 | - && get_frame_type (this_frame) == NORMAL_FRAME) | |
977 | + && (get_frame_type (this_frame) == NORMAL_FRAME | |
978 | + || get_frame_type (this_frame) == INLINE_FRAME)) | |
979 | return pc - 1; | |
980 | ||
981 | return pc; | |
982 | } | |
983 | ||
984 | -static int | |
985 | -pc_notcurrent (struct frame_info *frame) | |
986 | +void | |
987 | +find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal) | |
988 | { | |
989 | + struct frame_info *next_frame; | |
990 | + int notcurrent; | |
991 | + | |
992 | + /* If the next frame represents an inlined function call, this frame's | |
993 | + sal is the "call site" of that inlined function, which can not | |
994 | + be inferred from get_frame_pc. */ | |
995 | + next_frame = get_next_frame (frame); | |
996 | + if (frame_inlined_callees (frame) > 0) | |
997 | + { | |
998 | + struct symbol *sym; | |
999 | + | |
1000 | + if (next_frame) | |
1001 | + sym = get_frame_function (next_frame); | |
1002 | + else | |
1003 | + sym = inline_skipped_symbol (inferior_ptid); | |
1004 | + | |
1005 | + init_sal (sal); | |
1006 | + if (SYMBOL_LINE (sym) != 0) | |
1007 | + { | |
1008 | + sal->symtab = SYMBOL_SYMTAB (sym); | |
1009 | + sal->line = SYMBOL_LINE (sym); | |
1010 | + } | |
1011 | + else | |
1012 | + /* If the symbol does not have a location, we don't know where | |
1013 | + the call site is. Do not pretend to. This is jarring, but | |
1014 | + we can't do much better. */ | |
1015 | + sal->pc = get_frame_pc (frame); | |
1016 | + | |
1017 | + return; | |
1018 | + } | |
1019 | + | |
1020 | /* If FRAME is not the innermost frame, that normally means that | |
1021 | FRAME->pc points at the return instruction (which is *after* the | |
1022 | call instruction), and we want to get the line containing the | |
1023 | @@ -1631,15 +1766,8 @@ pc_notcurrent (struct frame_info *frame) | |
1024 | PC and such a PC indicates the current (rather than next) | |
1025 | instruction/line, consequently, for such cases, want to get the | |
1026 | line containing fi->pc. */ | |
1027 | - struct frame_info *next = get_next_frame (frame); | |
1028 | - int notcurrent = (next != NULL && get_frame_type (next) == NORMAL_FRAME); | |
1029 | - return notcurrent; | |
1030 | -} | |
1031 | - | |
1032 | -void | |
1033 | -find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal) | |
1034 | -{ | |
1035 | - (*sal) = find_pc_line (get_frame_pc (frame), pc_notcurrent (frame)); | |
1036 | + notcurrent = (get_frame_pc (frame) != get_frame_address_in_block (frame)); | |
1037 | + (*sal) = find_pc_line (get_frame_pc (frame), notcurrent); | |
1038 | } | |
1039 | ||
1040 | /* Per "frame.h", return the ``address'' of the frame. Code should | |
d566d21e | 1041 | Index: gdb-6.8.50.20090302/gdb/frame.h |
3a58abaf | 1042 | =================================================================== |
d566d21e | 1043 | --- gdb-6.8.50.20090302.orig/gdb/frame.h 2009-02-05 18:28:20.000000000 +0100 |
1044 | +++ gdb-6.8.50.20090302/gdb/frame.h 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
1045 | @@ -34,6 +34,9 @@ |
1046 | frame_unwind_WHAT...(): Unwind THIS frame's WHAT from the NEXT | |
1047 | frame. | |
1048 | ||
1049 | + get_stack_frame_WHAT...(): Get WHAT for THIS frame, but if THIS is | |
1050 | + inlined, skip to the containing stack frame. | |
1051 | + | |
1052 | put_frame_WHAT...(): Put a value into this frame (unsafe, need to | |
1053 | invalidate the frame / regcache afterwards) (better name more | |
1054 | strongly hinting at its unsafeness) | |
1055 | @@ -101,6 +104,10 @@ struct frame_id | |
1056 | Typically, it is set to the address of the entry point of the | |
1057 | frame's function (as returned by get_frame_func). | |
1058 | ||
1059 | + For inlined functions (INLINE_DEPTH != 0), this is the address of | |
1060 | + the first executed instruction in the block corresponding to the | |
1061 | + inlined function. | |
1062 | + | |
1063 | This field is valid only if code_addr_p is true. Otherwise, this | |
1064 | frame is considered to have a wildcard code address, i.e. one that | |
1065 | matches every address value in frame comparisons. */ | |
1066 | @@ -122,6 +129,10 @@ struct frame_id | |
1067 | unsigned int stack_addr_p : 1; | |
1068 | unsigned int code_addr_p : 1; | |
1069 | unsigned int special_addr_p : 1; | |
1070 | + | |
1071 | + /* The inline depth of this frame. A frame representing a "called" | |
1072 | + inlined function will have this set to a nonzero value. */ | |
1073 | + int inline_depth; | |
1074 | }; | |
1075 | ||
1076 | /* Methods for constructing and comparing Frame IDs. */ | |
1077 | @@ -157,6 +168,10 @@ extern struct frame_id frame_id_build_wi | |
1078 | non-zero .base). */ | |
1079 | extern int frame_id_p (struct frame_id l); | |
1080 | ||
1081 | +/* Returns non-zero when L is a valid frame representing an inlined | |
1082 | + function. */ | |
1083 | +extern int frame_id_inlined_p (struct frame_id l); | |
1084 | + | |
1085 | /* Returns non-zero when L and R identify the same frame, or, if | |
1086 | either L or R have a zero .func, then the same frame base. */ | |
1087 | extern int frame_id_eq (struct frame_id l, struct frame_id r); | |
1088 | @@ -177,6 +192,9 @@ enum frame_type | |
1089 | /* A fake frame, created by GDB when performing an inferior function | |
1090 | call. */ | |
1091 | DUMMY_FRAME, | |
1092 | + /* A frame representing an inlined function, associated with an | |
1093 | + upcoming (next, inner, younger) NORMAL_FRAME. */ | |
1094 | + INLINE_FRAME, | |
1095 | /* In a signal handler, various OSs handle this in various ways. | |
1096 | The main thing is that the frame may be far from normal. */ | |
1097 | SIGTRAMP_FRAME, | |
1098 | @@ -345,6 +363,7 @@ extern CORE_ADDR get_frame_base (struct | |
1099 | ||
1100 | instead, since that avoids the bug. */ | |
1101 | extern struct frame_id get_frame_id (struct frame_info *fi); | |
1102 | +extern struct frame_id get_stack_frame_id (struct frame_info *fi); | |
1103 | extern struct frame_id frame_unwind_id (struct frame_info *next_frame); | |
1104 | ||
1105 | /* Assuming that a frame is `normal', return its base-address, or 0 if | |
d566d21e | 1106 | Index: gdb-6.8.50.20090302/gdb/gdbthread.h |
3a58abaf | 1107 | =================================================================== |
d566d21e | 1108 | --- gdb-6.8.50.20090302.orig/gdb/gdbthread.h 2009-03-21 21:06:02.000000000 +0100 |
1109 | +++ gdb-6.8.50.20090302/gdb/gdbthread.h 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
1110 | @@ -83,6 +83,13 @@ struct thread_info |
1111 | This is how we know when we step into a subroutine call, and how | |
1112 | to set the frame for the breakpoint used to step out. */ | |
1113 | struct frame_id step_frame_id; | |
1114 | + | |
1115 | + /* Similarly, the frame ID of the underlying stack frame (skipping any | |
1116 | + inlined frames). */ | |
1117 | + struct frame_id step_stack_frame_id; | |
1118 | + | |
1119 | + /* The source file and line at the beginning of the current step | |
1120 | + operation. Only valid when step_frame_id is set. */ | |
1121 | int current_line; | |
1122 | struct symtab *current_symtab; | |
1123 | ||
d566d21e | 1124 | Index: gdb-6.8.50.20090302/gdb/infcall.c |
3a58abaf | 1125 | =================================================================== |
d566d21e | 1126 | --- gdb-6.8.50.20090302.orig/gdb/infcall.c 2009-03-21 21:06:02.000000000 +0100 |
1127 | +++ gdb-6.8.50.20090302/gdb/infcall.c 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
1128 | @@ -898,15 +898,8 @@ The program being debugged exited while |
1129 | ||
1130 | if (unwind_on_signal_p) | |
1131 | { | |
1132 | - /* The user wants the context restored. */ | |
1133 | - | |
1134 | - /* We must get back to the frame we were before the | |
1135 | - dummy call. */ | |
1136 | - dummy_frame_pop (dummy_id); | |
1137 | - | |
1138 | - /* We also need to restore inferior status to that before the | |
1139 | - dummy call. */ | |
1140 | - restore_inferior_status (inf_status); | |
1141 | + /* The user wants the context restored. Calling error will | |
1142 | + run inf_status_cleanup, which does all the work. */ | |
1143 | ||
1144 | /* FIXME: Insert a bunch of wrap_here; name can be very | |
1145 | long if it's a C++ name with arguments and stuff. */ | |
d566d21e | 1146 | Index: gdb-6.8.50.20090302/gdb/infcmd.c |
3a58abaf | 1147 | =================================================================== |
d566d21e | 1148 | --- gdb-6.8.50.20090302.orig/gdb/infcmd.c 2009-03-21 21:06:02.000000000 +0100 |
1149 | +++ gdb-6.8.50.20090302/gdb/infcmd.c 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
1150 | @@ -52,6 +52,7 @@ |
1151 | #include "cli/cli-decode.h" | |
1152 | #include "gdbthread.h" | |
1153 | #include "valprint.h" | |
1154 | +#include "inline-frame.h" | |
1155 | ||
1156 | /* Functions exported for general use, in inferior.h: */ | |
1157 | ||
1158 | @@ -744,6 +745,17 @@ Can't resume all threads and specify pro | |
1159 | continue_1 (all_threads); | |
1160 | } | |
1161 | \f | |
1162 | +/* Record the starting point of a "step" or "next" command. */ | |
1163 | + | |
1164 | +static void | |
1165 | +set_step_frame (struct thread_info *tp) | |
1166 | +{ | |
1167 | + struct symtab_and_line sal; | |
1168 | + | |
1169 | + find_frame_sal (get_current_frame (), &sal); | |
1170 | + set_step_info (tp, get_current_frame (), sal); | |
1171 | +} | |
1172 | + | |
1173 | /* Step until outside of current statement. */ | |
1174 | ||
1175 | static void | |
1176 | @@ -921,6 +933,20 @@ step_once (int skip_subroutines, int sin | |
1177 | THREAD is set. */ | |
1178 | struct thread_info *tp = inferior_thread (); | |
1179 | clear_proceed_status (); | |
1180 | + set_step_frame (tp); | |
1181 | + | |
1182 | + /* Step at an inlined function behaves like "down". */ | |
1183 | + if (!skip_subroutines && !single_inst | |
1184 | + && inline_skipped_frames (inferior_ptid)) | |
1185 | + { | |
1186 | + step_into_inline_frame (inferior_ptid); | |
1187 | + if (count > 1) | |
1188 | + step_once (skip_subroutines, single_inst, count - 1, thread); | |
1189 | + else | |
1190 | + /* Pretend that we've stopped. */ | |
1191 | + normal_stop (); | |
1192 | + return; | |
1193 | + } | |
1194 | ||
1195 | frame = get_current_frame (); | |
1196 | tp->step_frame_id = get_frame_id (frame); | |
1197 | @@ -1173,6 +1199,7 @@ until_next_command (int from_tty) | |
1198 | clear_proceed_status (); | |
1199 | ||
1200 | frame = get_current_frame (); | |
1201 | + set_step_frame (tp); | |
1202 | ||
1203 | /* Step until either exited from this function or greater | |
1204 | than the current line (if in symbolic section) or pc (if | |
1205 | @@ -1200,7 +1227,6 @@ until_next_command (int from_tty) | |
1206 | } | |
1207 | ||
1208 | tp->step_over_calls = STEP_OVER_ALL; | |
1209 | - tp->step_frame_id = get_frame_id (frame); | |
1210 | ||
1211 | tp->step_multi = 0; /* Only one call to proceed */ | |
1212 | ||
1213 | @@ -1533,6 +1559,37 @@ finish_command (char *arg, int from_tty) | |
1214 | ||
1215 | clear_proceed_status (); | |
1216 | ||
1217 | + /* Finishing from an inline frame is completely different. We don't | |
1218 | + try to show the "return value" - no way to locate it. So we do | |
1219 | + not need a completion. */ | |
1220 | + if (get_frame_type (get_selected_frame (_("No selected frame."))) | |
1221 | + == INLINE_FRAME) | |
1222 | + { | |
1223 | + struct thread_info *tp = inferior_thread (); | |
1224 | + | |
1225 | + /* Claim we are stepping in the calling frame. An empty step | |
1226 | + range means that we will stop once we aren't in a function | |
1227 | + called by that frame. We don't use the magic "1" value for | |
1228 | + step_range_end, because then infrun will think this is nexti, | |
1229 | + and not step over the rest of this inlined function call. */ | |
1230 | + struct symtab_and_line empty_sal; | |
1231 | + init_sal (&empty_sal); | |
1232 | + set_step_info (tp, frame, empty_sal); | |
1233 | + tp->step_range_start = tp->step_range_end = get_frame_pc (frame); | |
1234 | + tp->step_over_calls = STEP_OVER_ALL; | |
1235 | + | |
1236 | + /* Print info on the selected frame, including level number but not | |
1237 | + source. */ | |
1238 | + if (from_tty) | |
1239 | + { | |
1240 | + printf_filtered (_("Run till exit from ")); | |
1241 | + print_stack_frame (get_selected_frame (NULL), 1, LOCATION); | |
1242 | + } | |
1243 | + | |
1244 | + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1); | |
1245 | + return; | |
1246 | + } | |
1247 | + | |
1248 | /* Find the function we will return from. */ | |
1249 | ||
1250 | function = find_pc_function (get_frame_pc (get_selected_frame (NULL))); | |
d566d21e | 1251 | Index: gdb-6.8.50.20090302/gdb/inferior.h |
3a58abaf | 1252 | =================================================================== |
d566d21e | 1253 | --- gdb-6.8.50.20090302.orig/gdb/inferior.h 2009-03-21 21:06:02.000000000 +0100 |
1254 | +++ gdb-6.8.50.20090302/gdb/inferior.h 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
1255 | @@ -259,6 +259,9 @@ extern void error_is_running (void); |
1256 | /* Calls error_is_running if the current thread is running. */ | |
1257 | extern void ensure_not_running (void); | |
1258 | ||
1259 | +void set_step_info (struct thread_info *tp, struct frame_info *frame, | |
1260 | + struct symtab_and_line sal); | |
1261 | + | |
1262 | /* From infcmd.c */ | |
1263 | ||
1264 | extern void tty_command (char *, int); | |
d566d21e | 1265 | Index: gdb-6.8.50.20090302/gdb/infrun.c |
3a58abaf | 1266 | =================================================================== |
d566d21e | 1267 | --- gdb-6.8.50.20090302.orig/gdb/infrun.c 2009-03-21 21:06:04.000000000 +0100 |
1268 | +++ gdb-6.8.50.20090302/gdb/infrun.c 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
1269 | @@ -48,6 +48,7 @@ |
1270 | #include "gdb_assert.h" | |
1271 | #include "mi/mi-common.h" | |
1272 | #include "event-top.h" | |
1273 | +#include "inline-frame.h" | |
1274 | ||
1275 | /* Prototypes for local functions */ | |
1276 | ||
1277 | @@ -205,7 +206,7 @@ static unsigned char *signal_program; | |
1278 | ||
1279 | /* Value to pass to target_resume() to cause all threads to resume */ | |
1280 | ||
1281 | -#define RESUME_ALL (pid_to_ptid (-1)) | |
1282 | +#define RESUME_ALL minus_one_ptid | |
1283 | ||
1284 | /* Command list pointer for the "stop" placeholder. */ | |
1285 | ||
1286 | @@ -1151,6 +1152,8 @@ a command like `return' or `jump' to con | |
1287 | step = 0; | |
1288 | } | |
1289 | ||
1290 | + clear_inline_frame_state (resume_ptid); | |
1291 | + | |
1292 | if (debug_displaced | |
1293 | && use_displaced_stepping (gdbarch) | |
1294 | && tp->trap_expected) | |
1295 | @@ -1192,6 +1195,7 @@ clear_proceed_status_thread (struct thre | |
1296 | tp->step_range_start = 0; | |
1297 | tp->step_range_end = 0; | |
1298 | tp->step_frame_id = null_frame_id; | |
1299 | + tp->step_stack_frame_id = null_frame_id; | |
1300 | tp->step_over_calls = STEP_OVER_UNDEBUGGABLE; | |
1301 | tp->stop_requested = 0; | |
1302 | ||
1303 | @@ -1536,6 +1540,9 @@ init_wait_for_inferior (void) | |
1304 | init_infwait_state (); | |
1305 | ||
1306 | displaced_step_clear (); | |
1307 | + | |
1308 | + /* Discard any skipped inlined frames. */ | |
1309 | + clear_inline_frame_state (minus_one_ptid); | |
1310 | } | |
1311 | ||
1312 | \f | |
1313 | @@ -1591,7 +1598,7 @@ struct execution_control_state | |
1314 | int wait_some_more; | |
1315 | }; | |
1316 | ||
1317 | -void init_execution_control_state (struct execution_control_state *ecs); | |
1318 | +static void init_execution_control_state (struct execution_control_state *ecs); | |
1319 | ||
1320 | void handle_inferior_event (struct execution_control_state *ecs); | |
1321 | ||
d566d21e | 1322 | @@ -1975,10 +1982,21 @@ fetch_inferior_event (void *client_data) |
3a58abaf AM |
1323 | display_gdb_prompt (0); |
1324 | } | |
1325 | ||
1326 | +/* Record the frame and location we're currently stepping through. */ | |
1327 | +void | |
1328 | +set_step_info (struct thread_info *tp, struct frame_info *frame, | |
1329 | + struct symtab_and_line sal) | |
1330 | +{ | |
1331 | + tp->step_frame_id = get_frame_id (frame); | |
1332 | + tp->step_stack_frame_id = get_stack_frame_id (frame); | |
1333 | + tp->current_symtab = sal.symtab; | |
1334 | + tp->current_line = sal.line; | |
1335 | +} | |
1336 | + | |
1337 | /* Prepare an execution control state for looping through a | |
1338 | wait_for_inferior-type loop. */ | |
1339 | ||
1340 | -void | |
1341 | +static void | |
1342 | init_execution_control_state (struct execution_control_state *ecs) | |
1343 | { | |
1344 | ecs->random_signal = 0; | |
d566d21e | 1345 | @@ -1989,16 +2007,10 @@ init_execution_control_state (struct exe |
3a58abaf AM |
1346 | void |
1347 | init_thread_stepping_state (struct thread_info *tss) | |
1348 | { | |
1349 | - struct symtab_and_line sal; | |
1350 | - | |
1351 | tss->stepping_over_breakpoint = 0; | |
1352 | tss->step_after_step_resume_breakpoint = 0; | |
1353 | tss->stepping_through_solib_after_catch = 0; | |
1354 | tss->stepping_through_solib_catchpoints = NULL; | |
1355 | - | |
1356 | - sal = find_pc_line (tss->prev_pc, 0); | |
1357 | - tss->current_line = sal.line; | |
1358 | - tss->current_symtab = sal.symtab; | |
1359 | } | |
1360 | ||
1361 | /* Return the cached copy of the last pid/waitstatus returned by | |
d566d21e | 1362 | @@ -2212,6 +2224,22 @@ deal_with_syscall_event (struct executio |
3a58abaf AM |
1363 | } |
1364 | } | |
1365 | ||
1366 | +static int | |
1367 | +stepped_in_from (struct frame_info *frame, struct frame_id step_frame_id) | |
1368 | +{ | |
1369 | + for (frame = get_prev_frame (frame); | |
1370 | + frame != NULL; | |
1371 | + frame = get_prev_frame (frame)) | |
1372 | + { | |
1373 | + if (frame_id_eq (get_frame_id (frame), step_frame_id)) | |
1374 | + return 1; | |
1375 | + if (get_frame_type (frame) != INLINE_FRAME) | |
1376 | + break; | |
1377 | + } | |
1378 | + | |
1379 | + return 0; | |
1380 | +} | |
1381 | + | |
1382 | /* Given an execution control state that has been freshly filled in | |
1383 | by an event from the inferior, figure out what it means and take | |
1384 | appropriate action. */ | |
d566d21e | 1385 | @@ -2906,6 +2934,12 @@ targets should add new threads to the th |
3a58abaf AM |
1386 | ecs->random_signal = 0; |
1387 | stopped_by_random_signal = 0; | |
1388 | ||
1389 | + /* Hide inlined functions starting here, unless we just performed stepi or | |
1390 | + nexti. After stepi and nexti, always show the innermost frame (not any | |
1391 | + inline function call sites). */ | |
1392 | + if (ecs->event_thread->step_range_end != 1) | |
1393 | + skip_inline_frames (ecs->ptid); | |
1394 | + | |
1395 | if (ecs->event_thread->stop_signal == TARGET_SIGNAL_TRAP | |
1396 | && ecs->event_thread->trap_expected | |
1397 | && gdbarch_single_step_through_delay_p (current_gdbarch) | |
d566d21e | 1398 | @@ -3138,8 +3172,8 @@ process_event_stop_test: |
3a58abaf AM |
1399 | && ecs->event_thread->stop_signal != TARGET_SIGNAL_0 |
1400 | && (ecs->event_thread->step_range_start <= stop_pc | |
1401 | && stop_pc < ecs->event_thread->step_range_end) | |
1402 | - && frame_id_eq (get_frame_id (get_current_frame ()), | |
1403 | - ecs->event_thread->step_frame_id) | |
1404 | + && frame_id_eq (get_stack_frame_id (get_current_frame ()), | |
1405 | + ecs->event_thread->step_stack_frame_id) | |
1406 | && ecs->event_thread->step_resume_breakpoint == NULL) | |
1407 | { | |
1408 | /* The inferior is about to take a signal that will take it | |
d566d21e | 1409 | @@ -3525,10 +3559,10 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME ( |
3a58abaf AM |
1410 | NOTE: frame_id_eq will never report two invalid frame IDs as |
1411 | being equal, so to get into this block, both the current and | |
1412 | previous frame must have valid frame IDs. */ | |
1413 | - if (!frame_id_eq (get_frame_id (get_current_frame ()), | |
1414 | - ecs->event_thread->step_frame_id) | |
1415 | + if (!frame_id_eq (get_stack_frame_id (get_current_frame ()), | |
1416 | + ecs->event_thread->step_stack_frame_id) | |
1417 | && (frame_id_eq (frame_unwind_id (get_current_frame ()), | |
1418 | - ecs->event_thread->step_frame_id) | |
1419 | + ecs->event_thread->step_stack_frame_id) | |
1420 | || execution_direction == EXEC_REVERSE)) | |
1421 | { | |
1422 | CORE_ADDR real_stop_pc; | |
d566d21e | 1423 | @@ -3771,6 +3805,82 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME ( |
3a58abaf AM |
1424 | return; |
1425 | } | |
1426 | ||
1427 | + /* Look for "calls" to inlined functions, part one. If the inline | |
1428 | + frame machinery detected some skipped call sites, we have entered | |
1429 | + a new inline function. */ | |
1430 | + | |
1431 | + if (frame_id_eq (get_frame_id (get_current_frame ()), | |
1432 | + ecs->event_thread->step_frame_id) | |
1433 | + && inline_skipped_frames (ecs->ptid)) | |
1434 | + { | |
1435 | + struct symtab_and_line call_sal; | |
1436 | + | |
1437 | + if (debug_infrun) | |
1438 | + fprintf_unfiltered (gdb_stdlog, | |
1439 | + "infrun: stepped into inlined function\n"); | |
1440 | + | |
1441 | + find_frame_sal (get_current_frame (), &call_sal); | |
1442 | + | |
1443 | + if (ecs->event_thread->step_over_calls != STEP_OVER_ALL) | |
1444 | + { | |
1445 | + /* For "step", we're going to stop. But if the call site | |
1446 | + for this inlined function is on the same source line as | |
1447 | + we were previously stepping, go down into the function | |
1448 | + first. Otherwise stop at the call site. */ | |
1449 | + | |
1450 | + if (call_sal.line == ecs->event_thread->current_line | |
1451 | + && call_sal.symtab == ecs->event_thread->current_symtab) | |
1452 | + step_into_inline_frame (ecs->ptid); | |
1453 | + | |
1454 | + ecs->event_thread->stop_step = 1; | |
1455 | + print_stop_reason (END_STEPPING_RANGE, 0); | |
1456 | + stop_stepping (ecs); | |
1457 | + return; | |
1458 | + } | |
1459 | + else | |
1460 | + { | |
1461 | + /* For "next", we should stop at the call site if it is on a | |
1462 | + different source line. Otherwise continue through the | |
1463 | + inlined function. */ | |
1464 | + if (call_sal.line == ecs->event_thread->current_line | |
1465 | + && call_sal.symtab == ecs->event_thread->current_symtab) | |
1466 | + keep_going (ecs); | |
1467 | + else | |
1468 | + { | |
1469 | + ecs->event_thread->stop_step = 1; | |
1470 | + print_stop_reason (END_STEPPING_RANGE, 0); | |
1471 | + stop_stepping (ecs); | |
1472 | + } | |
1473 | + return; | |
1474 | + } | |
1475 | + } | |
1476 | + | |
1477 | + /* Look for "calls" to inlined functions, part two. If we are still | |
1478 | + in the same real function we were stepping through, but we have | |
1479 | + to go further up to find the exact frame ID, we are stepping | |
1480 | + through a more inlined call beyond its call site. */ | |
1481 | + | |
1482 | + if (get_frame_type (get_current_frame ()) == INLINE_FRAME | |
1483 | + && !frame_id_eq (get_frame_id (get_current_frame ()), | |
1484 | + ecs->event_thread->step_frame_id) | |
1485 | + && stepped_in_from (get_current_frame (), | |
1486 | + ecs->event_thread->step_frame_id)) | |
1487 | + { | |
1488 | + if (debug_infrun) | |
1489 | + fprintf_unfiltered (gdb_stdlog, | |
1490 | + "infrun: stepping through inlined function\n"); | |
1491 | + | |
1492 | + if (ecs->event_thread->step_over_calls == STEP_OVER_ALL) | |
1493 | + keep_going (ecs); | |
1494 | + else | |
1495 | + { | |
1496 | + ecs->event_thread->stop_step = 1; | |
1497 | + print_stop_reason (END_STEPPING_RANGE, 0); | |
1498 | + stop_stepping (ecs); | |
1499 | + } | |
1500 | + return; | |
1501 | + } | |
1502 | + | |
1503 | if ((stop_pc == stop_pc_sal.pc) | |
1504 | && (ecs->event_thread->current_line != stop_pc_sal.line | |
1505 | || ecs->event_thread->current_symtab != stop_pc_sal.symtab)) | |
d566d21e | 1506 | @@ -3796,9 +3906,7 @@ infrun: BPSTAT_WHAT_SET_LONGJMP_RESUME ( |
3a58abaf AM |
1507 | |
1508 | ecs->event_thread->step_range_start = stop_pc_sal.pc; | |
1509 | ecs->event_thread->step_range_end = stop_pc_sal.end; | |
1510 | - ecs->event_thread->step_frame_id = get_frame_id (get_current_frame ()); | |
1511 | - ecs->event_thread->current_line = stop_pc_sal.line; | |
1512 | - ecs->event_thread->current_symtab = stop_pc_sal.symtab; | |
1513 | + set_step_info (ecs->event_thread, get_current_frame (), stop_pc_sal); | |
1514 | ||
1515 | if (debug_infrun) | |
1516 | fprintf_unfiltered (gdb_stdlog, "infrun: keep going\n"); | |
d566d21e | 1517 | @@ -5050,6 +5158,7 @@ struct inferior_status |
3a58abaf AM |
1518 | CORE_ADDR step_range_start; |
1519 | CORE_ADDR step_range_end; | |
1520 | struct frame_id step_frame_id; | |
1521 | + struct frame_id step_stack_frame_id; | |
1522 | enum step_over_calls_kind step_over_calls; | |
1523 | CORE_ADDR step_resume_break_address; | |
1524 | int stop_after_trap; | |
d566d21e | 1525 | @@ -5079,6 +5188,7 @@ save_inferior_status (void) |
3a58abaf AM |
1526 | inf_status->step_range_start = tp->step_range_start; |
1527 | inf_status->step_range_end = tp->step_range_end; | |
1528 | inf_status->step_frame_id = tp->step_frame_id; | |
1529 | + inf_status->step_stack_frame_id = tp->step_stack_frame_id; | |
1530 | inf_status->step_over_calls = tp->step_over_calls; | |
1531 | inf_status->stop_after_trap = stop_after_trap; | |
1532 | inf_status->stop_soon = inf->stop_soon; | |
d566d21e | 1533 | @@ -5132,6 +5242,7 @@ restore_inferior_status (struct inferior |
3a58abaf AM |
1534 | tp->step_range_start = inf_status->step_range_start; |
1535 | tp->step_range_end = inf_status->step_range_end; | |
1536 | tp->step_frame_id = inf_status->step_frame_id; | |
1537 | + tp->step_stack_frame_id = inf_status->step_stack_frame_id; | |
1538 | tp->step_over_calls = inf_status->step_over_calls; | |
1539 | stop_after_trap = inf_status->stop_after_trap; | |
1540 | inf->stop_soon = inf_status->stop_soon; | |
d566d21e | 1541 | Index: gdb-6.8.50.20090302/gdb/inline-frame.c |
3a58abaf AM |
1542 | =================================================================== |
1543 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
d566d21e | 1544 | +++ gdb-6.8.50.20090302/gdb/inline-frame.c 2009-03-21 21:06:16.000000000 +0100 |
3a58abaf AM |
1545 | @@ -0,0 +1,382 @@ |
1546 | +/* Inline frame unwinder for GDB. | |
1547 | + | |
1548 | + Copyright (C) 2008 Free Software Foundation, Inc. | |
1549 | + | |
1550 | + This file is part of GDB. | |
1551 | + | |
1552 | + This program is free software; you can redistribute it and/or modify | |
1553 | + it under the terms of the GNU General Public License as published by | |
1554 | + the Free Software Foundation; either version 3 of the License, or | |
1555 | + (at your option) any later version. | |
1556 | + | |
1557 | + This program is distributed in the hope that it will be useful, | |
1558 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1559 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1560 | + GNU General Public License for more details. | |
1561 | + | |
1562 | + You should have received a copy of the GNU General Public License | |
1563 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
1564 | + | |
1565 | +#include "defs.h" | |
1566 | +#include "addrmap.h" | |
1567 | +#include "block.h" | |
1568 | +#include "frame-unwind.h" | |
1569 | +#include "inferior.h" | |
1570 | +#include "symtab.h" | |
1571 | +#include "vec.h" | |
1572 | + | |
1573 | +#include "gdb_assert.h" | |
1574 | + | |
1575 | +/* We need to save a few variables for every thread stopped at the | |
1576 | + virtual call site of an inlined function. If there was always a | |
1577 | + "struct thread_info", we could hang it off that; in the mean time, | |
1578 | + keep our own list. */ | |
1579 | +struct inline_state | |
1580 | +{ | |
1581 | + /* The thread this data relates to. It should be a currently | |
1582 | + stopped thread; we assume thread IDs never change while the | |
1583 | + thread is stopped. */ | |
1584 | + ptid_t ptid; | |
1585 | + | |
1586 | + /* The number of inlined functions we are skipping. Each of these | |
1587 | + functions can be stepped in to. */ | |
1588 | + int skipped_frames; | |
1589 | + | |
1590 | + /* Only valid if SKIPPED_FRAMES is non-zero. This is the PC used | |
1591 | + when calculating SKIPPED_FRAMES; used to check whether we have | |
1592 | + moved to a new location by user request. If so, we invalidate | |
1593 | + any skipped frames. */ | |
1594 | + CORE_ADDR saved_pc; | |
1595 | + | |
1596 | + /* Only valid if SKIPPED_FRAMES is non-zero. This is the symbol | |
1597 | + of the outermost skipped inline function. It's used to find the | |
1598 | + call site of the current frame. */ | |
1599 | + struct symbol *skipped_symbol; | |
1600 | +}; | |
1601 | + | |
1602 | +typedef struct inline_state inline_state_s; | |
1603 | +DEF_VEC_O(inline_state_s); | |
1604 | + | |
1605 | +static VEC(inline_state_s) *inline_states; | |
1606 | + | |
1607 | +/* Locate saved inlined frame state for PTID, if it exists. */ | |
1608 | + | |
1609 | +static struct inline_state * | |
1610 | +find_inline_frame_state (ptid_t ptid) | |
1611 | +{ | |
1612 | + struct inline_state *state; | |
1613 | + int ix; | |
1614 | + | |
1615 | + for (ix = 0; VEC_iterate (inline_state_s, inline_states, ix, state); ix++) | |
1616 | + { | |
1617 | + if (ptid_equal (state->ptid, ptid)) | |
1618 | + return state; | |
1619 | + } | |
1620 | + | |
1621 | + return NULL; | |
1622 | +} | |
1623 | + | |
1624 | +/* Allocate saved inlined frame state for PTID. */ | |
1625 | + | |
1626 | +static struct inline_state * | |
1627 | +allocate_inline_frame_state (ptid_t ptid) | |
1628 | +{ | |
1629 | + struct inline_state *state; | |
1630 | + | |
1631 | + state = VEC_safe_push (inline_state_s, inline_states, NULL); | |
1632 | + memset (state, 0, sizeof (*state)); | |
1633 | + state->ptid = ptid; | |
1634 | + | |
1635 | + return state; | |
1636 | +} | |
1637 | + | |
1638 | +/* Forget about any hidden inlined functions in PTID, which is new or | |
1639 | + about to be resumed. If PTID is minus_one_ptid, forget about all | |
1640 | + hidden inlined functions. */ | |
1641 | + | |
1642 | +void | |
1643 | +clear_inline_frame_state (ptid_t ptid) | |
1644 | +{ | |
1645 | + struct inline_state *state; | |
1646 | + int ix; | |
1647 | + | |
1648 | + if (ptid_equal (ptid, minus_one_ptid)) | |
1649 | + { | |
1650 | + VEC_free (inline_state_s, inline_states); | |
1651 | + return; | |
1652 | + } | |
1653 | + | |
1654 | + for (ix = 0; VEC_iterate (inline_state_s, inline_states, ix, state); ix++) | |
1655 | + if (ptid_equal (state->ptid, ptid)) | |
1656 | + { | |
1657 | + VEC_unordered_remove (inline_state_s, inline_states, ix); | |
1658 | + return; | |
1659 | + } | |
1660 | +} | |
1661 | + | |
1662 | +static void | |
1663 | +inline_frame_this_id (struct frame_info *this_frame, | |
1664 | + void **this_cache, | |
1665 | + struct frame_id *this_id) | |
1666 | +{ | |
1667 | + struct symbol *func; | |
1668 | + | |
1669 | + /* In order to have a stable frame ID for a given inline function, | |
1670 | + we must get the stack / special addresses from the underlying | |
1671 | + real frame's this_id method. So we must call get_prev_frame. | |
1672 | + Because we are inlined into some function, there must be previous | |
1673 | + frames, so this is safe - as long as we're careful not to | |
1674 | + create any cycles. */ | |
1675 | + *this_id = get_frame_id (get_prev_frame (this_frame)); | |
1676 | + | |
1677 | + /* We need a valid frame ID, so we need to be based on a valid | |
1678 | + frame. FSF submission NOTE: this would be a good assertion to | |
1679 | + apply to all frames, all the time. That would fix the ambiguity | |
1680 | + of null_frame_id (between "no/any frame" and "the outermost | |
1681 | + frame"). This will take work. */ | |
1682 | + gdb_assert (frame_id_p (*this_id)); | |
1683 | + | |
1684 | + /* Future work NOTE: Alexandre Oliva applied a patch to GCC 4.3 | |
1685 | + which generates DW_AT_entry_pc for inlined functions when | |
1686 | + possible. If this attribute is available, we should use it | |
1687 | + in the frame ID (and eventually, to set breakpoints). */ | |
1688 | + func = get_frame_function (this_frame); | |
1689 | + gdb_assert (func != NULL); | |
1690 | + (*this_id).code_addr = BLOCK_START (SYMBOL_BLOCK_VALUE (func)); | |
1691 | + (*this_id).inline_depth++; | |
1692 | +} | |
1693 | + | |
1694 | +static struct value * | |
1695 | +inline_frame_prev_register (struct frame_info *this_frame, void **this_cache, | |
1696 | + int regnum) | |
1697 | +{ | |
1698 | + /* Use get_frame_register_value instead of | |
1699 | + frame_unwind_got_register, to avoid requiring this frame's ID. | |
1700 | + This frame's ID depends on the previous frame's ID (unusual), and | |
1701 | + the previous frame's ID depends on this frame's unwound | |
1702 | + registers. If unwinding registers from this frame called | |
1703 | + get_frame_id, there would be a loop. | |
1704 | + | |
1705 | + Do not copy this code into any other unwinder! Inlined functions | |
1706 | + are special; other unwinders must not have a dependency on the | |
1707 | + previous frame's ID, and therefore can and should use | |
1708 | + frame_unwind_got_register instead. */ | |
1709 | + return get_frame_register_value (this_frame, regnum); | |
1710 | +} | |
1711 | + | |
1712 | +/* Check whether we are at an inlining site that does not already | |
1713 | + have an associated frame. */ | |
1714 | + | |
1715 | +static int | |
1716 | +inline_frame_sniffer (const struct frame_unwind *self, | |
1717 | + struct frame_info *this_frame, | |
1718 | + void **this_cache) | |
1719 | +{ | |
1720 | + CORE_ADDR this_pc; | |
1721 | + struct block *frame_block, *cur_block; | |
1722 | + int depth; | |
1723 | + struct frame_info *next_frame; | |
1724 | + struct inline_state *state = find_inline_frame_state (inferior_ptid); | |
1725 | + | |
1726 | + this_pc = get_frame_address_in_block (this_frame); | |
1727 | + frame_block = block_for_pc (this_pc); | |
1728 | + if (frame_block == NULL) | |
1729 | + return 0; | |
1730 | + | |
1731 | + /* Calculate DEPTH, the number of inlined functions at this | |
1732 | + location. */ | |
1733 | + depth = 0; | |
1734 | + cur_block = frame_block; | |
1735 | + while (BLOCK_SUPERBLOCK (cur_block)) | |
1736 | + { | |
1737 | + if (block_inlined_p (cur_block)) | |
1738 | + depth++; | |
1739 | + | |
1740 | + cur_block = BLOCK_SUPERBLOCK (cur_block); | |
1741 | + } | |
1742 | + | |
1743 | + /* Check how many inlined functions already have frames. */ | |
1744 | + for (next_frame = get_next_frame (this_frame); | |
1745 | + next_frame && get_frame_type (next_frame) == INLINE_FRAME; | |
1746 | + next_frame = get_next_frame (next_frame)) | |
1747 | + { | |
1748 | + gdb_assert (depth > 0); | |
1749 | + depth--; | |
1750 | + } | |
1751 | + | |
1752 | + /* If this is the topmost frame, or all frames above us are inlined, | |
1753 | + then check whether we were requested to skip some frames (so they | |
1754 | + can be stepped into later). */ | |
1755 | + if (state != NULL && state->skipped_frames > 0 && next_frame == NULL) | |
1756 | + { | |
1757 | + if (this_pc != state->saved_pc) | |
1758 | + state->skipped_frames = 0; | |
1759 | + else | |
1760 | + { | |
1761 | + gdb_assert (depth >= state->skipped_frames); | |
1762 | + depth -= state->skipped_frames; | |
1763 | + } | |
1764 | + } | |
1765 | + | |
1766 | + /* If all the inlined functions here already have frames, then pass | |
1767 | + to the normal unwinder for this PC. */ | |
1768 | + if (depth == 0) | |
1769 | + return 0; | |
1770 | + | |
1771 | + /* If the next frame is an inlined function, but not the outermost, then | |
1772 | + we are the next outer. If it is not an inlined function, then we | |
1773 | + are the innermost inlined function of a different real frame. */ | |
1774 | + return 1; | |
1775 | +} | |
1776 | + | |
1777 | +const struct frame_unwind inline_frame_unwinder = { | |
1778 | + INLINE_FRAME, | |
1779 | + inline_frame_this_id, | |
1780 | + inline_frame_prev_register, | |
1781 | + NULL, | |
1782 | + inline_frame_sniffer | |
1783 | +}; | |
1784 | + | |
1785 | +const struct frame_unwind *const inline_frame_unwind = &inline_frame_unwinder; | |
1786 | + | |
1787 | +/* Return non-zero if BLOCK, an inlined function block containing PC, | |
1788 | + has a group of contiguous instructions starting at PC (but not | |
1789 | + before it). */ | |
1790 | + | |
1791 | +static int | |
1792 | +block_starting_point_at (CORE_ADDR pc, struct block *block) | |
1793 | +{ | |
1794 | + struct blockvector *bv; | |
1795 | + struct block *new_block; | |
1796 | + | |
1797 | + bv = blockvector_for_pc (pc, NULL); | |
1798 | + if (BLOCKVECTOR_MAP (bv) == NULL) | |
1799 | + return 0; | |
1800 | + | |
1801 | + new_block = addrmap_find (BLOCKVECTOR_MAP (bv), pc - 1); | |
1802 | + if (new_block == NULL) | |
1803 | + return 1; | |
1804 | + | |
1805 | + if (new_block == block || contained_in (new_block, block)) | |
1806 | + return 0; | |
1807 | + | |
1808 | + /* The immediately preceeding address belongs to a different block, | |
1809 | + which is not a child of this one. Treat this as an entrance into | |
1810 | + BLOCK. */ | |
1811 | + return 1; | |
1812 | +} | |
1813 | + | |
1814 | +/* Skip all inlined functions whose call sites are at the current PC. | |
1815 | + Frames for the hidden functions will not appear in the backtrace until the | |
1816 | + user steps into them. */ | |
1817 | + | |
1818 | +void | |
1819 | +skip_inline_frames (ptid_t ptid) | |
1820 | +{ | |
1821 | + CORE_ADDR this_pc; | |
1822 | + struct block *frame_block, *cur_block; | |
1823 | + struct symbol *last_sym = NULL; | |
1824 | + int skip_count = 0; | |
1825 | + struct inline_state *state; | |
1826 | + | |
1827 | + /* This function is called right after reinitializing the frame | |
1828 | + cache. We try not to do more unwinding than absolutely | |
1829 | + necessary, for performance. */ | |
1830 | + this_pc = get_frame_pc (get_current_frame ()); | |
1831 | + frame_block = block_for_pc (this_pc); | |
1832 | + | |
1833 | + if (frame_block != NULL) | |
1834 | + { | |
1835 | + cur_block = frame_block; | |
1836 | + while (BLOCK_SUPERBLOCK (cur_block)) | |
1837 | + { | |
1838 | + if (block_inlined_p (cur_block)) | |
1839 | + { | |
1840 | + /* See comments in inline_frame_this_id about this use | |
1841 | + of BLOCK_START. */ | |
1842 | + if (BLOCK_START (cur_block) == this_pc | |
1843 | + || block_starting_point_at (this_pc, cur_block)) | |
1844 | + { | |
1845 | + skip_count++; | |
1846 | + last_sym = BLOCK_FUNCTION (cur_block); | |
1847 | + } | |
1848 | + else | |
1849 | + break; | |
1850 | + } | |
1851 | + cur_block = BLOCK_SUPERBLOCK (cur_block); | |
1852 | + } | |
1853 | + } | |
1854 | + | |
1855 | + gdb_assert (find_inline_frame_state (ptid) == NULL); | |
1856 | + state = allocate_inline_frame_state (ptid); | |
1857 | + state->skipped_frames = skip_count; | |
1858 | + state->saved_pc = this_pc; | |
1859 | + state->skipped_symbol = last_sym; | |
1860 | + | |
1861 | + if (skip_count != 0) | |
1862 | + reinit_frame_cache (); | |
1863 | +} | |
1864 | + | |
1865 | +/* Step into an inlined function by unhiding it. */ | |
1866 | + | |
1867 | +void | |
1868 | +step_into_inline_frame (ptid_t ptid) | |
1869 | +{ | |
1870 | + struct inline_state *state = find_inline_frame_state (ptid); | |
1871 | + | |
1872 | + gdb_assert (state != NULL && state->skipped_frames > 0); | |
1873 | + state->skipped_frames--; | |
1874 | + reinit_frame_cache (); | |
1875 | +} | |
1876 | + | |
1877 | +/* Return the number of hidden functions inlined into the current | |
1878 | + frame. */ | |
1879 | + | |
1880 | +int | |
1881 | +inline_skipped_frames (ptid_t ptid) | |
1882 | +{ | |
1883 | + struct inline_state *state = find_inline_frame_state (ptid); | |
1884 | + | |
1885 | + if (state == NULL) | |
1886 | + return 0; | |
1887 | + else | |
1888 | + return state->skipped_frames; | |
1889 | +} | |
1890 | + | |
1891 | +/* If one or more inlined functions are hidden, return the symbol for | |
1892 | + the function inlined into the current frame. */ | |
1893 | + | |
1894 | +struct symbol * | |
1895 | +inline_skipped_symbol (ptid_t ptid) | |
1896 | +{ | |
1897 | + struct inline_state *state = find_inline_frame_state (ptid); | |
1898 | + | |
1899 | + gdb_assert (state != NULL); | |
1900 | + return state->skipped_symbol; | |
1901 | +} | |
1902 | + | |
1903 | +/* Return the number of functions inlined into THIS_FRAME. Some of | |
1904 | + the callees may not have associated frames (see | |
1905 | + skip_inline_frames). */ | |
1906 | + | |
1907 | +int | |
1908 | +frame_inlined_callees (struct frame_info *this_frame) | |
1909 | +{ | |
1910 | + struct frame_info *next_frame; | |
1911 | + int inline_count = 0; | |
1912 | + | |
1913 | + /* First count how many inlined functions at this PC have frames | |
1914 | + above FRAME (are inlined into FRAME). */ | |
1915 | + for (next_frame = get_next_frame (this_frame); | |
1916 | + next_frame && get_frame_type (next_frame) == INLINE_FRAME; | |
1917 | + next_frame = get_next_frame (next_frame)) | |
1918 | + inline_count++; | |
1919 | + | |
1920 | + /* Simulate some most-inner inlined frames which were suppressed, so | |
1921 | + they can be stepped into later. If we are unwinding already | |
1922 | + outer frames from some non-inlined frame this does not apply. */ | |
1923 | + if (next_frame == NULL) | |
1924 | + inline_count += inline_skipped_frames (inferior_ptid); | |
1925 | + | |
1926 | + return inline_count; | |
1927 | +} | |
d566d21e | 1928 | Index: gdb-6.8.50.20090302/gdb/inline-frame.h |
3a58abaf AM |
1929 | =================================================================== |
1930 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
d566d21e | 1931 | +++ gdb-6.8.50.20090302/gdb/inline-frame.h 2009-03-21 21:06:16.000000000 +0100 |
3a58abaf AM |
1932 | @@ -0,0 +1,62 @@ |
1933 | +/* Definitions for inline frame support. | |
1934 | + | |
1935 | + Copyright (C) 2008 Free Software Foundation, Inc. | |
1936 | + | |
1937 | + This file is part of GDB. | |
1938 | + | |
1939 | + This program is free software; you can redistribute it and/or modify | |
1940 | + it under the terms of the GNU General Public License as published by | |
1941 | + the Free Software Foundation; either version 3 of the License, or | |
1942 | + (at your option) any later version. | |
1943 | + | |
1944 | + This program is distributed in the hope that it will be useful, | |
1945 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
1946 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
1947 | + GNU General Public License for more details. | |
1948 | + | |
1949 | + You should have received a copy of the GNU General Public License | |
1950 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
1951 | + | |
1952 | +#if !defined (INLINE_FRAME_H) | |
1953 | +#define INLINE_FRAME_H 1 | |
1954 | + | |
1955 | +struct frame_info; | |
1956 | +struct frame_unwind; | |
1957 | + | |
1958 | +/* The inline frame unwinder. */ | |
1959 | + | |
1960 | +extern const struct frame_unwind *const inline_frame_unwind; | |
1961 | + | |
1962 | +/* Skip all inlined functions whose call sites are at the current PC. | |
1963 | + Frames for the hidden functions will not appear in the backtrace until the | |
1964 | + user steps into them. */ | |
1965 | + | |
1966 | +void skip_inline_frames (ptid_t ptid); | |
1967 | + | |
1968 | +/* Forget about any hidden inlined functions in PTID, which is new or | |
1969 | + about to be resumed. If PTID is minus_one_ptid, forget about all | |
1970 | + hidden inlined functions. */ | |
1971 | + | |
1972 | +void clear_inline_frame_state (ptid_t ptid); | |
1973 | + | |
1974 | +/* Step into an inlined function by unhiding it. */ | |
1975 | + | |
1976 | +void step_into_inline_frame (ptid_t ptid); | |
1977 | + | |
1978 | +/* Return the number of hidden functions inlined into the current | |
1979 | + frame. */ | |
1980 | + | |
1981 | +int inline_skipped_frames (ptid_t ptid); | |
1982 | + | |
1983 | +/* If one or more inlined functions are hidden, return the symbol for | |
1984 | + the function inlined into the current frame. */ | |
1985 | + | |
1986 | +struct symbol *inline_skipped_symbol (ptid_t ptid); | |
1987 | + | |
1988 | +/* Return the number of functions inlined into THIS_FRAME. Some of | |
1989 | + the callees may not have associated frames (see | |
1990 | + skip_inline_frames). */ | |
1991 | + | |
1992 | +int frame_inlined_callees (struct frame_info *this_frame); | |
1993 | + | |
1994 | +#endif /* !defined (INLINE_FRAME_H) */ | |
d566d21e | 1995 | Index: gdb-6.8.50.20090302/gdb/minsyms.c |
3a58abaf | 1996 | =================================================================== |
d566d21e | 1997 | --- gdb-6.8.50.20090302.orig/gdb/minsyms.c 2009-03-21 21:06:03.000000000 +0100 |
1998 | +++ gdb-6.8.50.20090302/gdb/minsyms.c 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
1999 | @@ -795,7 +795,7 @@ prim_record_minimal_symbol_and_info (con |
2000 | ||
2001 | if (msym_bunch_index == BUNCH_SIZE) | |
2002 | { | |
2003 | - new = (struct msym_bunch *) xmalloc (sizeof (struct msym_bunch)); | |
2004 | + new = XCALLOC (1, struct msym_bunch); | |
2005 | msym_bunch_index = 0; | |
2006 | new->next = msym_bunch; | |
2007 | msym_bunch = new; | |
d566d21e | 2008 | Index: gdb-6.8.50.20090302/gdb/s390-tdep.c |
3a58abaf | 2009 | =================================================================== |
d566d21e | 2010 | --- gdb-6.8.50.20090302.orig/gdb/s390-tdep.c 2009-02-22 02:02:19.000000000 +0100 |
2011 | +++ gdb-6.8.50.20090302/gdb/s390-tdep.c 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
2012 | @@ -1182,6 +1182,7 @@ s390_prologue_frame_unwind_cache (struct |
2013 | CORE_ADDR prev_sp; | |
2014 | int frame_pointer; | |
2015 | int size; | |
2016 | + struct frame_info *next_frame; | |
2017 | ||
2018 | /* Try to find the function start address. If we can't find it, we don't | |
2019 | bother searching for it -- with modern compilers this would be mostly | |
2020 | @@ -1215,7 +1216,10 @@ s390_prologue_frame_unwind_cache (struct | |
2021 | /* FIXME: cagney/2004-05-01: This sanity check shouldn't be | |
2022 | needed, instead the code should simpliy rely on its | |
2023 | analysis. */ | |
2024 | - if (get_next_frame (this_frame) | |
2025 | + next_frame = get_next_frame (this_frame); | |
2026 | + while (next_frame && get_frame_type (next_frame) == INLINE_FRAME) | |
2027 | + next_frame = get_next_frame (next_frame); | |
2028 | + if (next_frame | |
2029 | && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME) | |
2030 | return 0; | |
2031 | ||
2032 | @@ -1261,8 +1265,11 @@ s390_prologue_frame_unwind_cache (struct | |
2033 | This can only happen in an innermost frame. */ | |
2034 | /* FIXME: cagney/2004-05-01: This sanity check shouldn't be needed, | |
2035 | instead the code should simpliy rely on its analysis. */ | |
2036 | + next_frame = get_next_frame (this_frame); | |
2037 | + while (next_frame && get_frame_type (next_frame) == INLINE_FRAME) | |
2038 | + next_frame = get_next_frame (next_frame); | |
2039 | if (size > 0 | |
2040 | - && (!get_next_frame (this_frame) | |
2041 | + && (next_frame == NULL | |
2042 | || get_frame_type (get_next_frame (this_frame)) != NORMAL_FRAME)) | |
2043 | { | |
2044 | /* See the comment in s390_in_function_epilogue_p on why this is | |
d566d21e | 2045 | Index: gdb-6.8.50.20090302/gdb/stack.c |
3a58abaf | 2046 | =================================================================== |
d566d21e | 2047 | --- gdb-6.8.50.20090302.orig/gdb/stack.c 2009-03-21 21:06:02.000000000 +0100 |
2048 | +++ gdb-6.8.50.20090302/gdb/stack.c 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
2049 | @@ -45,6 +45,7 @@ |
2050 | #include "valprint.h" | |
2051 | #include "gdbthread.h" | |
2052 | #include "cp-support.h" | |
2053 | +#include "inline-frame.h" | |
2054 | ||
2055 | #include "gdb_assert.h" | |
2056 | #include <ctype.h> | |
2057 | @@ -98,6 +99,30 @@ print_stack_frame_stub (void *args) | |
2058 | return 0; | |
2059 | } | |
2060 | ||
2061 | +/* Return 1 if we should display the address in addition to the location, | |
2062 | + because we are in the middle of a statement. */ | |
2063 | + | |
2064 | +static int | |
2065 | +frame_show_address (struct frame_info *frame, | |
2066 | + struct symtab_and_line sal) | |
2067 | +{ | |
2068 | + /* If there is a line number, but no PC, then there is no location | |
2069 | + information associated with this sal. The only way that should | |
2070 | + happen is for the call sites of inlined functions (SAL comes from | |
2071 | + find_frame_sal). Otherwise, we would have some PC range if the | |
2072 | + SAL came from a line table. */ | |
2073 | + if (sal.line != 0 && sal.pc == 0 && sal.end == 0) | |
2074 | + { | |
2075 | + if (get_next_frame (frame) == NULL) | |
2076 | + gdb_assert (inline_skipped_frames (inferior_ptid) > 0); | |
2077 | + else | |
2078 | + gdb_assert (get_frame_type (get_next_frame (frame)) == INLINE_FRAME); | |
2079 | + return 0; | |
2080 | + } | |
2081 | + | |
2082 | + return get_frame_pc (frame) != sal.pc; | |
2083 | +} | |
2084 | + | |
2085 | /* Show or print a stack frame FRAME briefly. The output is format | |
2086 | according to PRINT_LEVEL and PRINT_WHAT printing the frame's | |
2087 | relative level, function name, argument list, and file name and | |
2088 | @@ -538,7 +563,7 @@ print_frame_info (struct frame_info *fra | |
2089 | { | |
2090 | int done = 0; | |
2091 | int mid_statement = ((print_what == SRC_LINE) | |
2092 | - && (get_frame_pc (frame) != sal.pc)); | |
2093 | + && frame_show_address (frame, sal)); | |
2094 | ||
2095 | if (annotation_level) | |
2096 | done = identify_source_line (sal.symtab, sal.line, mid_statement, | |
2097 | @@ -591,7 +616,7 @@ find_frame_funname (struct frame_info *f | |
2098 | *funname = NULL; | |
2099 | *funlang = language_unknown; | |
2100 | ||
2101 | - func = find_pc_function (get_frame_address_in_block (frame)); | |
2102 | + func = get_frame_function (frame); | |
2103 | if (func) | |
2104 | { | |
2105 | /* In certain pathological cases, the symtabs give the wrong | |
2106 | @@ -612,8 +637,13 @@ find_frame_funname (struct frame_info *f | |
2107 | changed (and we'll create a find_pc_minimal_function or some | |
2108 | such). */ | |
2109 | ||
2110 | - struct minimal_symbol *msymbol = | |
2111 | - lookup_minimal_symbol_by_pc (get_frame_address_in_block (frame)); | |
2112 | + struct minimal_symbol *msymbol = NULL; | |
2113 | + | |
2114 | + /* Don't attempt to do this for inlined functions, which do not | |
2115 | + have a corresponding minimal symbol. */ | |
2116 | + if (!block_inlined_p (SYMBOL_BLOCK_VALUE (func))) | |
2117 | + msymbol | |
2118 | + = lookup_minimal_symbol_by_pc (get_frame_address_in_block (frame)); | |
2119 | ||
2120 | if (msymbol != NULL | |
2121 | && (SYMBOL_VALUE_ADDRESS (msymbol) | |
2122 | @@ -687,7 +717,7 @@ print_frame (struct frame_info *frame, i | |
2123 | } | |
2124 | get_user_print_options (&opts); | |
2125 | if (opts.addressprint) | |
2126 | - if (get_frame_pc (frame) != sal.pc || !sal.symtab | |
2127 | + if (frame_show_address (frame, sal) || !sal.symtab | |
2128 | || print_what == LOC_AND_ADDRESS) | |
2129 | { | |
2130 | annotate_frame_address (); | |
2131 | @@ -867,8 +897,16 @@ parse_frame_specification_1 (const char | |
2132 | { | |
2133 | if (frame_id_eq (id, get_frame_id (fid))) | |
2134 | { | |
2135 | - while (frame_id_eq (id, frame_unwind_id (fid))) | |
2136 | - fid = get_prev_frame (fid); | |
2137 | + struct frame_info *prev_frame; | |
2138 | + | |
2139 | + while (1) | |
2140 | + { | |
2141 | + prev_frame = get_prev_frame (fid); | |
2142 | + if (!prev_frame | |
2143 | + || !frame_id_eq (id, get_frame_id (prev_frame))) | |
2144 | + break; | |
2145 | + fid = prev_frame; | |
2146 | + } | |
2147 | return fid; | |
2148 | } | |
2149 | } | |
2150 | @@ -1002,8 +1040,10 @@ frame_info (char *addr_exp, int from_tty | |
2151 | printf_filtered (_(" Outermost frame: %s\n"), | |
2152 | frame_stop_reason_string (reason)); | |
2153 | } | |
2154 | - | |
2155 | - if (calling_frame_info) | |
2156 | + else if (get_frame_type (fi) == INLINE_FRAME) | |
2157 | + printf_filtered (" inlined into frame %d", | |
2158 | + frame_relative_level (get_prev_frame (fi))); | |
2159 | + else | |
2160 | { | |
2161 | printf_filtered (" called by frame at "); | |
2162 | fputs_filtered (paddress (get_frame_base (calling_frame_info)), | |
2163 | @@ -1465,7 +1505,9 @@ print_frame_local_vars (struct frame_inf | |
2164 | if (print_block_frame_locals (block, frame, num_tabs, stream)) | |
2165 | values_printed = 1; | |
2166 | /* After handling the function's top-level block, stop. Don't | |
2167 | - continue to its superblock, the block of per-file symbols. */ | |
2168 | + continue to its superblock, the block of per-file symbols. | |
2169 | + Also do not continue to the containing function of an inlined | |
2170 | + function. */ | |
2171 | if (BLOCK_FUNCTION (block)) | |
2172 | break; | |
2173 | block = BLOCK_SUPERBLOCK (block); | |
2174 | @@ -1536,7 +1578,9 @@ print_frame_label_vars (struct frame_inf | |
2175 | return; | |
2176 | ||
2177 | /* After handling the function's top-level block, stop. Don't | |
2178 | - continue to its superblock, the block of per-file symbols. */ | |
2179 | + continue to its superblock, the block of per-file symbols. | |
2180 | + Also do not continue to the containing function of an inlined | |
2181 | + function. */ | |
2182 | if (BLOCK_FUNCTION (block)) | |
2183 | break; | |
2184 | block = BLOCK_SUPERBLOCK (block); | |
d566d21e | 2185 | @@ -1806,6 +1850,9 @@ return_command (char *retval_exp, int fr |
3a58abaf AM |
2186 | thisframe = get_selected_frame ("No selected frame."); |
2187 | thisfun = get_frame_function (thisframe); | |
2188 | ||
2189 | + if (get_frame_type (get_current_frame ()) == INLINE_FRAME) | |
2190 | + error (_("Can not force return from an inlined function.")); | |
2191 | + | |
2192 | /* Compute the return value. If the computation triggers an error, | |
2193 | let it bail. If the return type can't be handled, set | |
2194 | RETURN_VALUE to NULL, and QUERY_PREFIX to an informational | |
d566d21e | 2195 | Index: gdb-6.8.50.20090302/gdb/symtab.c |
3a58abaf | 2196 | =================================================================== |
d566d21e | 2197 | --- gdb-6.8.50.20090302.orig/gdb/symtab.c 2009-03-21 21:06:03.000000000 +0100 |
2198 | +++ gdb-6.8.50.20090302/gdb/symtab.c 2009-03-21 21:06:49.000000000 +0100 | |
2199 | @@ -1417,11 +1417,14 @@ lookup_symbol_aux_local (const char *nam | |
2200 | sym = lookup_symbol_aux_block (name, linkage_name, block_iterator, domain); | |
3a58abaf AM |
2201 | if (sym != NULL) |
2202 | return sym; | |
2203 | + | |
2204 | + if (BLOCK_FUNCTION (block) != NULL && block_inlined_p (block)) | |
2205 | + break; | |
2206 | ||
d566d21e | 2207 | block_iterator = BLOCK_SUPERBLOCK (block_iterator); |
3a58abaf AM |
2208 | } |
2209 | ||
2210 | - /* We've reached the global block without finding a result. */ | |
2211 | + /* We've reached the edge of the function without finding a result. */ | |
2212 | ||
2213 | return NULL; | |
2214 | } | |
d566d21e | 2215 | @@ -2678,6 +2681,7 @@ find_function_start_sal (struct symbol * |
3a58abaf AM |
2216 | |
2217 | CORE_ADDR pc; | |
2218 | struct symtab_and_line sal; | |
2219 | + struct block *b, *function_block; | |
2220 | ||
2221 | pc = BLOCK_START (block); | |
2222 | fixup_symbol_section (sym, objfile); | |
d566d21e | 2223 | @@ -2716,6 +2720,25 @@ find_function_start_sal (struct symbol * |
3a58abaf AM |
2224 | |
2225 | sal.pc = pc; | |
2226 | ||
2227 | + /* Check if we are now inside an inlined function. If we can, | |
2228 | + use the call site of the function instead. */ | |
2229 | + b = block_for_pc_sect (sal.pc, SYMBOL_OBJ_SECTION (sym)); | |
2230 | + function_block = NULL; | |
2231 | + while (b != NULL) | |
2232 | + { | |
2233 | + if (BLOCK_FUNCTION (b) != NULL && block_inlined_p (b)) | |
2234 | + function_block = b; | |
2235 | + else if (BLOCK_FUNCTION (b) != NULL) | |
2236 | + break; | |
2237 | + b = BLOCK_SUPERBLOCK (b); | |
2238 | + } | |
2239 | + if (function_block != NULL | |
2240 | + && SYMBOL_LINE (BLOCK_FUNCTION (function_block)) != 0) | |
2241 | + { | |
2242 | + sal.line = SYMBOL_LINE (BLOCK_FUNCTION (function_block)); | |
2243 | + sal.symtab = SYMBOL_SYMTAB (BLOCK_FUNCTION (function_block)); | |
2244 | + } | |
2245 | + | |
2246 | return sal; | |
2247 | } | |
2248 | ||
d566d21e | 2249 | @@ -3738,6 +3761,24 @@ add_macro_name (const char *name, const |
3a58abaf AM |
2250 | datum->text, datum->word); |
2251 | } | |
2252 | ||
2253 | +static void | |
2254 | +completion_list_add_fields (struct symbol *sym, char *sym_text, | |
2255 | + int sym_text_len, char *text, char *word) | |
2256 | +{ | |
2257 | + if (SYMBOL_CLASS (sym) == LOC_TYPEDEF) | |
2258 | + { | |
2259 | + struct type *t = SYMBOL_TYPE (sym); | |
2260 | + enum type_code c = TYPE_CODE (t); | |
2261 | + int j; | |
2262 | + | |
2263 | + if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT) | |
2264 | + for (j = TYPE_N_BASECLASSES (t); j < TYPE_NFIELDS (t); j++) | |
2265 | + if (TYPE_FIELD_NAME (t, j)) | |
2266 | + completion_list_add_name (TYPE_FIELD_NAME (t, j), | |
2267 | + sym_text, sym_text_len, text, word); | |
2268 | + } | |
2269 | +} | |
2270 | + | |
2271 | char ** | |
2272 | default_make_symbol_completion_list (char *text, char *word) | |
2273 | { | |
d566d21e | 2274 | @@ -3750,9 +3791,9 @@ default_make_symbol_completion_list (cha |
3a58abaf AM |
2275 | struct partial_symtab *ps; |
2276 | struct minimal_symbol *msymbol; | |
2277 | struct objfile *objfile; | |
2278 | - struct block *b, *surrounding_static_block = 0; | |
2279 | + struct block *b; | |
2280 | + const struct block *surrounding_static_block, *surrounding_global_block; | |
2281 | struct dict_iterator iter; | |
2282 | - int j; | |
2283 | struct partial_symbol **psym; | |
2284 | /* The symbol we are completing on. Points in same buffer as text. */ | |
2285 | char *sym_text; | |
d566d21e | 2286 | @@ -3862,41 +3903,43 @@ default_make_symbol_completion_list (cha |
3a58abaf AM |
2287 | } |
2288 | ||
2289 | /* Search upwards from currently selected frame (so that we can | |
2290 | - complete on local vars. */ | |
2291 | + complete on local vars). Also catch fields of types defined in | |
2292 | + this places which match our text string. Only complete on types | |
2293 | + visible from current context. */ | |
2294 | + | |
2295 | + b = get_selected_block (0); | |
2296 | + surrounding_static_block = block_static_block (b); | |
2297 | + surrounding_global_block = block_global_block (b); | |
2298 | + if (surrounding_static_block != NULL) | |
2299 | + while (b != surrounding_static_block) | |
2300 | + { | |
2301 | + QUIT; | |
2302 | ||
2303 | - for (b = get_selected_block (0); b != NULL; b = BLOCK_SUPERBLOCK (b)) | |
2304 | - { | |
2305 | - if (!BLOCK_SUPERBLOCK (b)) | |
2306 | - { | |
2307 | - surrounding_static_block = b; /* For elmin of dups */ | |
2308 | - } | |
2309 | + ALL_BLOCK_SYMBOLS (b, iter, sym) | |
2310 | + { | |
2311 | + COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, | |
2312 | + word); | |
2313 | + completion_list_add_fields (sym, sym_text, sym_text_len, text, | |
2314 | + word); | |
2315 | + } | |
2316 | ||
2317 | - /* Also catch fields of types defined in this places which match our | |
2318 | - text string. Only complete on types visible from current context. */ | |
2319 | + /* Stop when we encounter an enclosing function. Do not stop for | |
2320 | + non-inlined functions - the locals of the enclosing function | |
2321 | + are in scope for a nested function. */ | |
2322 | + if (BLOCK_FUNCTION (b) != NULL && block_inlined_p (b)) | |
2323 | + break; | |
2324 | + b = BLOCK_SUPERBLOCK (b); | |
2325 | + } | |
2326 | ||
2327 | - ALL_BLOCK_SYMBOLS (b, iter, sym) | |
2328 | - { | |
2329 | - QUIT; | |
2330 | - COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word); | |
2331 | - if (SYMBOL_CLASS (sym) == LOC_TYPEDEF) | |
2332 | - { | |
2333 | - struct type *t = SYMBOL_TYPE (sym); | |
2334 | - enum type_code c = TYPE_CODE (t); | |
2335 | + /* Add fields from the file's types; symbols will be added below. */ | |
2336 | ||
2337 | - if (c == TYPE_CODE_UNION || c == TYPE_CODE_STRUCT) | |
2338 | - { | |
2339 | - for (j = TYPE_N_BASECLASSES (t); j < TYPE_NFIELDS (t); j++) | |
2340 | - { | |
2341 | - if (TYPE_FIELD_NAME (t, j)) | |
2342 | - { | |
2343 | - completion_list_add_name (TYPE_FIELD_NAME (t, j), | |
2344 | - sym_text, sym_text_len, text, word); | |
2345 | - } | |
2346 | - } | |
2347 | - } | |
2348 | - } | |
2349 | - } | |
2350 | - } | |
2351 | + if (surrounding_static_block != NULL) | |
2352 | + ALL_BLOCK_SYMBOLS (surrounding_static_block, iter, sym) | |
2353 | + completion_list_add_fields (sym, sym_text, sym_text_len, text, word); | |
2354 | + | |
2355 | + if (surrounding_global_block != NULL) | |
2356 | + ALL_BLOCK_SYMBOLS (surrounding_global_block, iter, sym) | |
2357 | + completion_list_add_fields (sym, sym_text, sym_text_len, text, word); | |
2358 | ||
2359 | /* Go through the symtabs and check the externs and statics for | |
2360 | symbols which match. */ | |
d566d21e | 2361 | @@ -3915,9 +3958,6 @@ default_make_symbol_completion_list (cha |
3a58abaf AM |
2362 | { |
2363 | QUIT; | |
2364 | b = BLOCKVECTOR_BLOCK (BLOCKVECTOR (s), STATIC_BLOCK); | |
2365 | - /* Don't do this block twice. */ | |
2366 | - if (b == surrounding_static_block) | |
2367 | - continue; | |
2368 | ALL_BLOCK_SYMBOLS (b, iter, sym) | |
2369 | { | |
2370 | COMPLETION_LIST_ADD_SYMBOL (sym, sym_text, sym_text_len, text, word); | |
d566d21e | 2371 | @@ -4384,6 +4424,25 @@ skip_prologue_using_sal (CORE_ADDR func_ |
3a58abaf AM |
2372 | line mark the prologue -> body transition. */ |
2373 | if (sal.line >= prologue_sal.line) | |
2374 | break; | |
2375 | + | |
2376 | + /* The line number is smaller. Check that it's from the | |
2377 | + same function, not something inlined. If it's inlined, | |
2378 | + then there is no point comparing the line numbers. */ | |
2379 | + bl = block_for_pc (prologue_sal.end); | |
2380 | + while (bl) | |
2381 | + { | |
2382 | + if (block_inlined_p (bl)) | |
2383 | + break; | |
2384 | + if (BLOCK_FUNCTION (bl)) | |
2385 | + { | |
2386 | + bl = NULL; | |
2387 | + break; | |
2388 | + } | |
2389 | + bl = BLOCK_SUPERBLOCK (bl); | |
2390 | + } | |
2391 | + if (bl != NULL) | |
2392 | + break; | |
2393 | + | |
2394 | /* The case in which compiler's optimizer/scheduler has | |
2395 | moved instructions into the prologue. We look ahead in | |
2396 | the function looking for address ranges whose | |
d566d21e | 2397 | Index: gdb-6.8.50.20090302/gdb/symtab.h |
3a58abaf | 2398 | =================================================================== |
d566d21e | 2399 | --- gdb-6.8.50.20090302.orig/gdb/symtab.h 2009-03-21 21:06:02.000000000 +0100 |
2400 | +++ gdb-6.8.50.20090302/gdb/symtab.h 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
2401 | @@ -556,9 +556,18 @@ struct symbol |
2402 | ||
2403 | unsigned is_argument : 1; | |
2404 | ||
2405 | - /* Line number of definition. FIXME: Should we really make the assumption | |
2406 | - that nobody will try to debug files longer than 64K lines? What about | |
2407 | - machine generated programs? */ | |
2408 | + /* Whether this is an inlined function (class LOC_BLOCK only). */ | |
2409 | + unsigned is_inlined : 1; | |
2410 | + | |
2411 | + /* Line number of this symbol's definition, except for inlined | |
2412 | + functions. For an inlined function (class LOC_BLOCK and | |
2413 | + SYMBOL_INLINED set) this is the line number of the function's call | |
2414 | + site. Inlined function symbols are not definitions, and they are | |
2415 | + never found by symbol table lookup. | |
2416 | + | |
2417 | + FIXME: Should we really make the assumption that nobody will try | |
2418 | + to debug files longer than 64K lines? What about machine | |
2419 | + generated programs? */ | |
2420 | ||
2421 | unsigned short line; | |
2422 | ||
2423 | @@ -589,6 +598,7 @@ struct symbol | |
2424 | #define SYMBOL_DOMAIN(symbol) (symbol)->domain | |
2425 | #define SYMBOL_CLASS(symbol) (symbol)->aclass | |
2426 | #define SYMBOL_IS_ARGUMENT(symbol) (symbol)->is_argument | |
2427 | +#define SYMBOL_INLINED(symbol) (symbol)->is_inlined | |
2428 | #define SYMBOL_TYPE(symbol) (symbol)->type | |
2429 | #define SYMBOL_LINE(symbol) (symbol)->line | |
2430 | #define SYMBOL_SYMTAB(symbol) (symbol)->symtab | |
d566d21e | 2431 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.base/break.exp |
3a58abaf | 2432 | =================================================================== |
d566d21e | 2433 | --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.base/break.exp 2009-01-19 20:05:01.000000000 +0100 |
2434 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.base/break.exp 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
2435 | @@ -880,6 +880,13 @@ gdb_expect { |
2436 | # marker4() is defined at line 46 when compiled with -DPROTOTYPES | |
2437 | pass "run until breakpoint set at small function, optimized file (line bp_location14)" | |
2438 | } | |
2439 | + -re "Breakpoint $decimal, factorial \\(.*\\) .*\{\r\n$gdb_prompt" { | |
2440 | + # GCC 4.3 emits bad line number information - see gcc/36748. | |
2441 | + if { [test_compiler_info "gcc-4-3-*"] } { | |
2442 | + setup_xfail *-*-* | |
2443 | + } | |
2444 | + fail "run until breakpoint set at small function, optimized file" | |
2445 | + } | |
2446 | -re ".*$gdb_prompt " { | |
2447 | fail "run until breakpoint set at small function, optimized file" | |
2448 | } | |
d566d21e | 2449 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.cp/annota2.exp |
3a58abaf | 2450 | =================================================================== |
d566d21e | 2451 | --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.cp/annota2.exp 2009-01-03 06:58:04.000000000 +0100 |
2452 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.cp/annota2.exp 2009-03-21 21:06:16.000000000 +0100 | |
3a58abaf AM |
2453 | @@ -119,10 +119,11 @@ gdb_expect { |
2454 | # continue until exit | |
2455 | # this will test: | |
2456 | # annotate-exited | |
2457 | +# `a.x is 1' is asynchronous regarding to `frames-invalid'. | |
2458 | # | |
2459 | send_gdb "continue\n" | |
2460 | gdb_expect { | |
2461 | - -re "\r\n\032\032post-prompt\r\nContinuing.\r\n\r\n\032\032starting\r\n\r\n\032\032frames-invalid\r\na.x is 1\r\n\r\n\032\032exited 0\r\n\r\nProgram exited normally.\r\n\r\n\032\032stopped\r\n$gdb_prompt$" \ | |
2462 | + -re "\r\n\032\032post-prompt\r\nContinuing.\r\n\r\n\032\032starting\r\n(\r\n\032\032frames-invalid\r\n)*a.x is 1\r\n(\r\n\032\032frames-invalid\r\n)*\r\n\032\032exited 0\r\n\r\nProgram exited normally.\r\n\r\n\032\032stopped\r\n$gdb_prompt$" \ | |
2463 | { pass "continue until exit" } | |
2464 | -re ".*$gdb_prompt$" { fail "continue to exit" } | |
2465 | timeout { fail "continue to exit (timeout)" } | |
d566d21e | 2466 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.c |
3a58abaf AM |
2467 | =================================================================== |
2468 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
d566d21e | 2469 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.c 2009-03-21 21:06:16.000000000 +0100 |
3a58abaf AM |
2470 | @@ -0,0 +1,47 @@ |
2471 | +/* Copyright (C) 2008 Free Software Foundation, Inc. | |
2472 | + | |
2473 | + This program is free software; you can redistribute it and/or modify | |
2474 | + it under the terms of the GNU General Public License as published by | |
2475 | + the Free Software Foundation; either version 3 of the License, or | |
2476 | + (at your option) any later version. | |
2477 | + | |
2478 | + This program is distributed in the hope that it will be useful, | |
2479 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
2480 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
2481 | + GNU General Public License for more details. | |
2482 | + | |
2483 | + You should have received a copy of the GNU General Public License | |
2484 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
2485 | + | |
2486 | +int x, y; | |
2487 | +volatile int result; | |
2488 | + | |
2489 | +void bar(void); | |
2490 | + | |
2491 | +inline int func1(void) | |
2492 | +{ | |
2493 | + bar (); | |
2494 | + return x * y; | |
2495 | +} | |
2496 | + | |
2497 | +inline int func2(void) | |
2498 | +{ | |
2499 | + return x * func1 (); | |
2500 | +} | |
2501 | + | |
2502 | +int main (void) | |
2503 | +{ | |
2504 | + int val; | |
2505 | + | |
2506 | + x = 7; | |
2507 | + y = 8; | |
2508 | + bar (); | |
2509 | + | |
2510 | + val = func1 (); | |
2511 | + result = val; | |
2512 | + | |
2513 | + val = func2 (); | |
2514 | + result = val; | |
2515 | + | |
2516 | + return 0; | |
2517 | +} | |
d566d21e | 2518 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.exp |
3a58abaf AM |
2519 | =================================================================== |
2520 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
d566d21e | 2521 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.exp 2009-03-21 21:06:17.000000000 +0100 |
3a58abaf AM |
2522 | @@ -0,0 +1,63 @@ |
2523 | +# Copyright 2008 Free Software Foundation, Inc. | |
2524 | + | |
2525 | +# This program is free software; you can redistribute it and/or modify | |
2526 | +# it under the terms of the GNU General Public License as published by | |
2527 | +# the Free Software Foundation; either version 3 of the License, or | |
2528 | +# (at your option) any later version. | |
2529 | +# | |
2530 | +# This program is distributed in the hope that it will be useful, | |
2531 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
2532 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
2533 | +# GNU General Public License for more details. | |
2534 | +# | |
2535 | +# You should have received a copy of the GNU General Public License | |
2536 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
2537 | + | |
2538 | +set testfile "inline-bt" | |
2539 | +set srcfile ${testfile}.c | |
2540 | +set srcfile2 "inline-markers.c" | |
2541 | +set fullsrcfile "${srcdir}/${subdir}/${srcfile}" | |
2542 | +set fullsrcfile2 "${srcdir}/${subdir}/${srcfile2}" | |
2543 | +set sources [list ${fullsrcfile} ${fullsrcfile2}] | |
2544 | +set binfile ${objdir}/${subdir}/${testfile} | |
2545 | + | |
2546 | +if { [gdb_compile ${sources} ${binfile} \ | |
2547 | + executable {debug optimize=-O2}] != "" } { | |
2548 | + untested inline-bt.exp | |
2549 | + return -1 | |
2550 | +} | |
2551 | + | |
2552 | +gdb_exit | |
2553 | +gdb_start | |
2554 | +gdb_reinitialize_dir $srcdir/$subdir | |
2555 | +gdb_load ${binfile} | |
2556 | + | |
2557 | +runto_main | |
2558 | + | |
2559 | +get_compiler_info $binfile | |
2560 | +get_debug_format | |
2561 | +if { [skip_inline_frame_tests] } { | |
2562 | + untested inline-bt.exp | |
2563 | + return | |
2564 | +} | |
2565 | + | |
2566 | +set line1 [gdb_get_line_number "set breakpoint 1 here" ${fullsrcfile2}] | |
2567 | +gdb_breakpoint $srcfile2:$line1 | |
2568 | + | |
2569 | +gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (1)" | |
2570 | +gdb_test "backtrace" "#0 bar.*#1 .*main.*" "backtrace from bar (1)" | |
2571 | +gdb_test "info frame" ".*called by frame.*" "bar not inlined" | |
2572 | + | |
2573 | +gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (2)" | |
2574 | +gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*main.*" \ | |
2575 | + "backtrace from bar (2)" | |
2576 | +gdb_test "up" "#1 .*func1.*" "up from bar (2)" | |
2577 | +gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (2)" | |
2578 | + | |
2579 | +gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (3)" | |
2580 | +gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*func2.*#3 .*main.*" \ | |
2581 | + "backtrace from bar (3)" | |
2582 | +gdb_test "up" "#1 .*func1.*" "up from bar (3)" | |
2583 | +gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (3)" | |
2584 | +gdb_test "up" "#2 .*func2.*" "up from func1 (3)" | |
2585 | +gdb_test "info frame" ".*inlined into frame.*" "func2 inlined (3)" | |
d566d21e | 2586 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.c |
3a58abaf AM |
2587 | =================================================================== |
2588 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
d566d21e | 2589 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.c 2009-03-21 21:06:17.000000000 +0100 |
3a58abaf AM |
2590 | @@ -0,0 +1,85 @@ |
2591 | +/* Copyright (C) 2008 Free Software Foundation, Inc. | |
2592 | + | |
2593 | + This program is free software; you can redistribute it and/or modify | |
2594 | + it under the terms of the GNU General Public License as published by | |
2595 | + the Free Software Foundation; either version 3 of the License, or | |
2596 | + (at your option) any later version. | |
2597 | + | |
2598 | + This program is distributed in the hope that it will be useful, | |
2599 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
2600 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
2601 | + GNU General Public License for more details. | |
2602 | + | |
2603 | + You should have received a copy of the GNU General Public License | |
2604 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
2605 | + | |
2606 | +int x, y; | |
2607 | +volatile int result; | |
2608 | + | |
2609 | +void bar(void); | |
2610 | +void marker(void); | |
2611 | +void noinline(void); | |
2612 | + | |
2613 | +inline int func1(void) | |
2614 | +{ | |
2615 | + bar (); | |
2616 | + return x * y; | |
2617 | +} | |
2618 | + | |
2619 | +inline int func2(void) | |
2620 | +{ | |
2621 | + return x * func1 (); | |
2622 | +} | |
2623 | + | |
2624 | +inline void func3(void) | |
2625 | +{ | |
2626 | + bar (); | |
2627 | +} | |
2628 | + | |
2629 | +inline void outer_inline1(void) | |
2630 | +{ | |
2631 | + noinline (); | |
2632 | +} | |
2633 | + | |
2634 | +inline void outer_inline2(void) | |
2635 | +{ | |
2636 | + outer_inline1 (); | |
2637 | +} | |
2638 | + | |
2639 | +int main (void) | |
2640 | +{ /* start of main */ | |
2641 | + int val; | |
2642 | + | |
2643 | + x = 7; | |
2644 | + y = 8; | |
2645 | + | |
2646 | + result = func1 (); | |
2647 | + result = func2 (); | |
2648 | + marker (); | |
2649 | + | |
2650 | + result = 0; | |
2651 | + result = 0; /* set breakpoint 3 here */ | |
2652 | + | |
2653 | + func1 (); /* first call */ | |
2654 | + func1 (); /* second call */ | |
2655 | + marker (); | |
2656 | + | |
2657 | + result = 0; | |
2658 | + result = 0; /* set breakpoint 4 here */ | |
2659 | + | |
2660 | + func1 (); | |
2661 | + func3 (); | |
2662 | + marker (); | |
2663 | + | |
2664 | + result = 0; | |
2665 | + result = 0; /* set breakpoint 5 here */ | |
2666 | + | |
2667 | + marker (); | |
2668 | + func1 (); | |
2669 | + func3 (); | |
2670 | + marker (); /* set breakpoint 6 here */ | |
2671 | + | |
2672 | + outer_inline2 (); | |
2673 | + | |
2674 | + return 0; | |
2675 | +} | |
d566d21e | 2676 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.exp |
3a58abaf AM |
2677 | =================================================================== |
2678 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
d566d21e | 2679 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.exp 2009-03-21 21:06:17.000000000 +0100 |
3a58abaf AM |
2680 | @@ -0,0 +1,279 @@ |
2681 | +# Copyright 2008 Free Software Foundation, Inc. | |
2682 | + | |
2683 | +# This program is free software; you can redistribute it and/or modify | |
2684 | +# it under the terms of the GNU General Public License as published by | |
2685 | +# the Free Software Foundation; either version 3 of the License, or | |
2686 | +# (at your option) any later version. | |
2687 | +# | |
2688 | +# This program is distributed in the hope that it will be useful, | |
2689 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
2690 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
2691 | +# GNU General Public License for more details. | |
2692 | +# | |
2693 | +# You should have received a copy of the GNU General Public License | |
2694 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
2695 | + | |
2696 | +set testfile "inline-cmds" | |
2697 | +set srcfile "${testfile}.c" | |
2698 | +set srcfile2 "inline-markers.c" | |
2699 | +set fullsrcfile "${srcdir}/${subdir}/${srcfile}" | |
2700 | +set fullsrcfile2 "${srcdir}/${subdir}/${srcfile2}" | |
2701 | +set sources [list ${fullsrcfile} ${fullsrcfile2}] | |
2702 | +set binfile ${objdir}/${subdir}/${testfile} | |
2703 | + | |
2704 | +if { [gdb_compile $sources ${binfile} \ | |
2705 | + executable {debug optimize=-O2}] != "" } { | |
2706 | + untested inline-cmds.exp | |
2707 | + return -1 | |
2708 | +} | |
2709 | + | |
2710 | +gdb_exit | |
2711 | +gdb_start | |
2712 | +gdb_reinitialize_dir $srcdir/$subdir | |
2713 | +gdb_load ${binfile} | |
2714 | + | |
2715 | +gdb_test "set listsize 1" "" | |
2716 | + | |
2717 | +runto_main | |
2718 | + | |
2719 | +get_compiler_info $binfile | |
2720 | +get_debug_format | |
2721 | +if { [skip_inline_frame_tests] } { | |
2722 | + untested inline-cmds.exp | |
2723 | + return | |
2724 | +} | |
2725 | + | |
2726 | +# First, check that the things we expected to be inlined really were, | |
2727 | +# and those that shouldn't be weren't. | |
2728 | +set line1 [gdb_get_line_number "set breakpoint 1 here" ${fullsrcfile2}] | |
2729 | +gdb_breakpoint $srcfile2:$line1 | |
2730 | +set line2 [gdb_get_line_number "set breakpoint 2 here" ${fullsrcfile2}] | |
2731 | +gdb_breakpoint $srcfile2:$line2 | |
2732 | + | |
2733 | +gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (1)" | |
2734 | +gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*main.*" \ | |
2735 | + "backtrace from bar (1)" | |
2736 | +gdb_test "up" "#1 .*func1.*" "up from bar (1)" | |
2737 | +gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (1)" | |
2738 | + | |
2739 | +gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (2)" | |
2740 | +gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*func2.*#3 .*main.*" \ | |
2741 | + "backtrace from bar (2)" | |
2742 | +gdb_test "up" "#1 .*func1.*" "up from bar (2)" | |
2743 | +gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (2)" | |
2744 | +gdb_test "up" "#2 .*func2.*" "up from func1 (2)" | |
2745 | +gdb_test "info frame" ".*inlined into frame.*" "func2 inlined (2)" | |
2746 | + | |
2747 | +gdb_test "continue" ".*set breakpoint 2 here.*" "continue to marker" | |
2748 | +gdb_test "backtrace" "#0 marker.*#1 .*main.*" "backtrace from marker" | |
2749 | +gdb_test "info frame" ".*called by frame.*" "marker not inlined" | |
2750 | + | |
2751 | +# Next, check that we can next over inlined functions. We should not end up | |
2752 | +# inside any of them. | |
2753 | +delete_breakpoints | |
2754 | +runto_main | |
2755 | + | |
2756 | +# The lines before the first inlined call. | |
2757 | +set first "x = 7|y = 8" | |
2758 | + | |
2759 | +# Some extra lines that end up in our stepping due to code motion. | |
2760 | +set opt "start of main|result = 0" | |
2761 | + | |
2762 | +# We start this test with a "list" instead of a "next", in case the | |
2763 | +# first non-prologue instruction in main comes from the inlined function. | |
2764 | +set msg "next over inlined functions" | |
2765 | +gdb_test_multiple "list" $msg { | |
2766 | + -re "($first|result = func1|result = func2|$opt).*$gdb_prompt $" { | |
2767 | + send_gdb "next\r" | |
2768 | + exp_continue | |
2769 | + } | |
2770 | + -re "marker \\\(\\\);\r\n$gdb_prompt $" { | |
2771 | + pass $msg | |
2772 | + } | |
2773 | +} | |
2774 | + | |
2775 | +# Check that when next shows the call of func1, it has not happened yet. | |
2776 | +runto_main | |
2777 | + | |
2778 | +# Like the return value of gdb_test: -1 something is wrong, 0 passed, 1 failed. | |
2779 | +set bt_test -1 | |
2780 | +set x_test -1 | |
2781 | + | |
2782 | +set msg "next past inlined func1" | |
2783 | +gdb_test_multiple "list" $msg { | |
2784 | + -re "($first|$opt).*$gdb_prompt $" { | |
2785 | + send_gdb "next\r" | |
2786 | + exp_continue | |
2787 | + } | |
2788 | + -re "result = func1 \\\(\\\);\r\n$gdb_prompt $" { | |
2789 | + # Check whether x has been set. If 0, we may be doing something | |
2790 | + # else associated with this line besides the inlined call - e.g. | |
2791 | + # loading the address of result. If 7, we may be at the call site. | |
2792 | + # If 15, though, we are past the call and back at the store to | |
2793 | + # result - that's bad, we should have stepped out of func1 and | |
2794 | + # kept stepping until the line changed. | |
2795 | + set x_val -1 | |
2796 | + gdb_test_multiple "print x" "" { | |
2797 | + -re "\\\$$decimal = (\[0-9\]*)\r\n$gdb_prompt $" { | |
2798 | + set x_val $expect_out(1,string) | |
2799 | + } | |
2800 | + -re "$gdb_prompt $" { } | |
2801 | + } | |
2802 | + if { $x_val == 0 || $x_val == 7 } { | |
2803 | + if { $x_test != 1 } { | |
2804 | + set x_test 0 | |
2805 | + } | |
2806 | + } else { | |
2807 | + set x_test 1 | |
2808 | + } | |
2809 | + | |
2810 | + # func1 should not show up on backtraces yet. | |
2811 | + if { $bt_test != 1 } { | |
2812 | + set bt_test [gdb_test "backtrace" "#0 \[^#]*main.*" ""] | |
2813 | + } | |
2814 | + | |
2815 | + send_gdb "next\r" | |
2816 | + exp_continue | |
2817 | + } | |
2818 | + | |
2819 | + -re "result = func2 \\\(\\\);\r\n$gdb_prompt $" { | |
2820 | + pass $msg | |
2821 | + } | |
2822 | +} | |
2823 | + | |
2824 | +if { $x_test == 0 } { | |
2825 | + pass "print x before func1" | |
2826 | +} else { | |
2827 | + fail "print x before func1" | |
2828 | +} | |
2829 | + | |
2830 | +if { $bt_test == 0 } { | |
2831 | + pass "backtrace does not include func1" | |
2832 | +} else { | |
2833 | + fail "backtrace does not include func1" | |
2834 | +} | |
2835 | + | |
2836 | +# Next, check that we can single step into inlined functions. We should always | |
2837 | +# "stop" at the call sites before entering them. | |
2838 | +runto_main | |
2839 | + | |
2840 | +set msg "step into func1" | |
2841 | +set saw_call_site 0 | |
2842 | +gdb_test_multiple "list" $msg { | |
2843 | + -re "($first|$opt).*$gdb_prompt $" { | |
2844 | + send_gdb "step\r" | |
2845 | + exp_continue | |
2846 | + } | |
2847 | + -re "result = func1.*$gdb_prompt $" { | |
2848 | + set saw_call_site 1 | |
2849 | + send_gdb "step\r" | |
2850 | + exp_continue | |
2851 | + } | |
2852 | + -re "func1 \\\(\\\) at .*\r\n$decimal.*bar \\\(\\\);\r\n$gdb_prompt $" { | |
2853 | + if { $saw_call_site } { | |
2854 | + pass $msg | |
2855 | + } else { | |
2856 | + fail $msg | |
2857 | + } | |
2858 | + } | |
2859 | +} | |
2860 | + | |
2861 | +# Check finish out of an inlined function. | |
2862 | +set msg "finish from func1" | |
2863 | +gdb_test_multiple "finish" $msg { | |
2864 | + -re "result = func1 \\\(\\\);\r\n$gdb_prompt $" { | |
2865 | + pass $msg | |
2866 | + } | |
2867 | + -re "($first|$opt).*$gdb_prompt $" { | |
2868 | + # Whoops. We finished, but ended up back at an earlier line. Keep | |
2869 | + # trying. | |
2870 | + send_gdb "step\r" | |
2871 | + exp_continue | |
2872 | + } | |
2873 | + -re "func1 \\\(\\\) at .*\r\n$decimal.*bar \\\(\\\);\r\n$gdb_prompt $" { | |
2874 | + send_gdb "finish\r" | |
2875 | + exp_continue | |
2876 | + } | |
2877 | +} | |
2878 | + | |
2879 | +# Test some corner cases involving consecutive inlined functions. | |
2880 | +set line3 [gdb_get_line_number "set breakpoint 3 here"] | |
2881 | +gdb_breakpoint $line3 | |
2882 | +gdb_continue_to_breakpoint "consecutive func1" | |
2883 | + | |
2884 | +gdb_test "next" ".*func1 .*first call.*" "next to first func1" | |
2885 | +set msg "next to second func1" | |
2886 | +gdb_test_multiple "next" $msg { | |
2887 | + -re ".*func1 .*second call.*$gdb_prompt $" { | |
2888 | + pass $msg | |
2889 | + } | |
2890 | + -re ".*marker .*$gdb_prompt $" { | |
2891 | + # This assembles to two consecutive call instructions. | |
2892 | + # Both appear to be at the same line, because they're | |
2893 | + # in the body of the same inlined function. This is | |
2894 | + # reasonable for the line table. GDB should take the | |
2895 | + # containing block and/or function into account when | |
2896 | + # deciding how far to step. The single line table entry | |
2897 | + # is actually two consecutive instances of the same line. | |
2898 | + kfail gdb/NNNN $msg | |
2899 | + } | |
2900 | +} | |
2901 | + | |
2902 | +# It is easier when the two inlined functions are not on the same line. | |
2903 | +set line4 [gdb_get_line_number "set breakpoint 4 here"] | |
2904 | +gdb_breakpoint $line4 | |
2905 | +gdb_continue_to_breakpoint "func1 then func3" | |
2906 | + | |
2907 | +gdb_test "next" ".*func1 \\\(\\\);" "next to func1 before func3" | |
2908 | +gdb_test "next" ".*func3 \\\(\\\);" "next to func3" | |
2909 | + | |
2910 | +# Test finishing out of one thing and into another. | |
2911 | +set line5 [gdb_get_line_number "set breakpoint 5 here"] | |
2912 | +gdb_breakpoint $line5 | |
2913 | +gdb_continue_to_breakpoint "finish into func1" | |
2914 | + | |
2915 | +gdb_test "next" ".*marker \\\(\\\);" "next to finish marker" | |
2916 | +gdb_test "step" ".*set breakpoint 2 here.*" "step into finish marker" | |
2917 | +gdb_test "finish" "func1 \\\(\\\);" "finish from marker to func1" | |
2918 | + | |
2919 | +gdb_test "step" "bar \\\(\\\);" "step into func1 for finish" | |
2920 | +gdb_test "finish" "func3 \\\(\\\);" "finish from func1 to func3" | |
2921 | + | |
2922 | +# Test a deeper call stack. | |
2923 | +set line6 [gdb_get_line_number "set breakpoint 6 here"] | |
2924 | +gdb_breakpoint $line6 | |
2925 | +gdb_continue_to_breakpoint "before the outer_inline call" | |
2926 | +gdb_test "step" "marker \\\(\\\) at .*" "reach 1 the outer_inline call" | |
2927 | +gdb_test "finish" "main \\\(\\\) at .*outer_inline2 \\\(\\\);" "reach outer_inline2" | |
2928 | +gdb_test "bt" "#0 main.*" "backtrace at main of outer_inline" | |
2929 | +gdb_test "step" "outer_inline2 \\\(\\\) at .*" "enter outer_inline2" | |
2930 | +gdb_test "bt" "#0 outer_inline2.*#1 main.*" "backtrace at outer_inline2" | |
2931 | +gdb_test "step" "outer_inline1 \\\(\\\) at .*" "enter outer_inline1 from outer_inline2" | |
2932 | + | |
2933 | +set msg "backtrace at outer_inline1" | |
2934 | +gdb_test_multiple "bt" $msg { | |
2935 | + -re "#0 outer_inline1.*#1 outer_inline2.*#2 main.*$gdb_prompt $" { | |
2936 | + pass $msg | |
2937 | + } | |
2938 | + -re "#0 $hex in outer_inline1.*#1 outer_inline2.*#2 main.*$gdb_prompt $" { | |
2939 | + # Binutils PR gas/6717. Gas moves .loc past .p2align and the | |
2940 | + # leading nop of the inlined call appears to be on the same line | |
2941 | + # as main's call to marker. | |
2942 | + xfail $msg | |
2943 | + gdb_test "step" "noinline \\\(\\\);" "step to call of noinline" | |
2944 | + } | |
2945 | +} | |
2946 | + | |
2947 | +gdb_test "step" "noinline \\\(\\\) at .*" "enter noinline from outer_inline1" | |
2948 | +gdb_test "bt" "#0 noinline.*#1 .*outer_inline1.*#2 .*outer_inline2.*#3 main.*" "backtrace at noinline from outer_inline1" | |
2949 | +gdb_test "step" "inlined_fn \\\(\\\) at .*" "enter inlined_fn from noinline" | |
2950 | +gdb_test "bt" "#0 inlined_fn.*#1 noinline.*#2 .*outer_inline1.*#3 .*outer_inline2.*#4 main.*" "backtrace at inlined_fn from noinline" | |
2951 | +gdb_test "info frame" ".*inlined into frame.*" "inlined_fn from noinline inlined" | |
2952 | +gdb_test "up" "#1 noinline.*" "up to noinline" | |
2953 | +gdb_test "info frame" ".*\n called by frame.*" "noinline from outer_inline1 not inlined" | |
2954 | +gdb_test "up" "#2 .*outer_inline1.*" "up to outer_inline1" | |
2955 | +gdb_test "info frame" ".*inlined into frame.*" "outer_inline1 inlined" | |
2956 | +gdb_test "up" "#3 .*outer_inline2.*" "up to outer_inline2" | |
2957 | +gdb_test "info frame" ".*inlined into frame.*" "outer_inline2 inlined" | |
2958 | +gdb_test "up" "#4 main.*" "up from outer_inline2" | |
2959 | +gdb_test "info frame" ".*\n caller of frame.*" "main not inlined" | |
d566d21e | 2960 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.c |
3a58abaf AM |
2961 | =================================================================== |
2962 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
d566d21e | 2963 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.c 2009-03-21 21:06:17.000000000 +0100 |
3a58abaf AM |
2964 | @@ -0,0 +1,52 @@ |
2965 | +/* Copyright (C) 2008 Free Software Foundation, Inc. | |
2966 | + | |
2967 | + This program is free software; you can redistribute it and/or modify | |
2968 | + it under the terms of the GNU General Public License as published by | |
2969 | + the Free Software Foundation; either version 3 of the License, or | |
2970 | + (at your option) any later version. | |
2971 | + | |
2972 | + This program is distributed in the hope that it will be useful, | |
2973 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
2974 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
2975 | + GNU General Public License for more details. | |
2976 | + | |
2977 | + You should have received a copy of the GNU General Public License | |
2978 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
2979 | + | |
2980 | +int x, y; | |
2981 | +volatile int result; | |
2982 | +volatile int *array_p; | |
2983 | + | |
2984 | +void bar(void); | |
2985 | + | |
2986 | +inline int func1(int arg1) | |
2987 | +{ | |
2988 | + int array[64]; | |
2989 | + array_p = array; | |
2990 | + array[0] = result; | |
2991 | + array[1] = arg1; | |
2992 | + bar (); | |
2993 | + return x * y + array_p[0] * arg1; | |
2994 | +} | |
2995 | + | |
2996 | +inline int func2(int arg2) | |
2997 | +{ | |
2998 | + return x * func1 (arg2); | |
2999 | +} | |
3000 | + | |
3001 | +int main (void) | |
3002 | +{ | |
3003 | + int val; | |
3004 | + | |
3005 | + x = 7; | |
3006 | + y = 8; | |
3007 | + bar (); | |
3008 | + | |
3009 | + val = func1 (result); | |
3010 | + result = val; | |
3011 | + | |
3012 | + val = func2 (result); | |
3013 | + result = val; | |
3014 | + | |
3015 | + return 0; | |
3016 | +} | |
d566d21e | 3017 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.exp |
3a58abaf AM |
3018 | =================================================================== |
3019 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
d566d21e | 3020 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.exp 2009-03-21 21:06:17.000000000 +0100 |
3a58abaf AM |
3021 | @@ -0,0 +1,118 @@ |
3022 | +# Copyright 2008 Free Software Foundation, Inc. | |
3023 | + | |
3024 | +# This program is free software; you can redistribute it and/or modify | |
3025 | +# it under the terms of the GNU General Public License as published by | |
3026 | +# the Free Software Foundation; either version 3 of the License, or | |
3027 | +# (at your option) any later version. | |
3028 | +# | |
3029 | +# This program is distributed in the hope that it will be useful, | |
3030 | +# but WITHOUT ANY WARRANTY; without even the implied warranty of | |
3031 | +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
3032 | +# GNU General Public License for more details. | |
3033 | +# | |
3034 | +# You should have received a copy of the GNU General Public License | |
3035 | +# along with this program. If not, see <http://www.gnu.org/licenses/>. | |
3036 | + | |
3037 | +set testfile "inline-locals" | |
3038 | +set srcfile ${testfile}.c | |
3039 | +set srcfile2 "inline-markers.c" | |
3040 | +set fullsrcfile "${srcdir}/${subdir}/${srcfile}" | |
3041 | +set fullsrcfile2 "${srcdir}/${subdir}/${srcfile2}" | |
3042 | +set sources [list ${fullsrcfile} ${fullsrcfile2}] | |
3043 | +set binfile ${objdir}/${subdir}/${testfile} | |
3044 | + | |
3045 | +if { [gdb_compile ${sources} ${binfile} \ | |
3046 | + executable {debug optimize=-O2}] != "" } { | |
3047 | + untested inline-locals.exp | |
3048 | + return -1 | |
3049 | +} | |
3050 | + | |
3051 | +gdb_exit | |
3052 | +gdb_start | |
3053 | +gdb_reinitialize_dir $srcdir/$subdir | |
3054 | +gdb_load ${binfile} | |
3055 | + | |
3056 | +runto_main | |
3057 | + | |
3058 | +get_compiler_info $binfile | |
3059 | +get_debug_format | |
3060 | +if { [skip_inline_var_tests] } { | |
3061 | + untested inline-bt.exp | |
3062 | + return | |
3063 | +} | |
3064 | + | |
3065 | +set no_frames [skip_inline_frame_tests] | |
3066 | + | |
3067 | +set line1 [gdb_get_line_number "set breakpoint 1 here" ${fullsrcfile2}] | |
3068 | +gdb_breakpoint $srcfile2:$line1 | |
3069 | + | |
3070 | +gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (1)" | |
3071 | + | |
3072 | +gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (2)" | |
3073 | + | |
3074 | +if { ! $no_frames } { | |
3075 | + gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*main.*" \ | |
3076 | + "backtrace from bar (2)" | |
3077 | + gdb_test "up" "#1 .*func1 .* at .*" "up from bar (2)" | |
3078 | + gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (2)" | |
3079 | + gdb_test "info locals" "array = {.*}" "info locals above bar (2)" | |
3080 | + | |
3081 | + set msg "info args above bar (2)" | |
3082 | + gdb_test_multiple "info args" $msg { | |
3083 | + -re "arg1 = $decimal\r\n$gdb_prompt $" { | |
3084 | + pass $msg | |
3085 | + } | |
3086 | + -re "arg1 = <value optimized out>\r\n$gdb_prompt $" { | |
3087 | + # GCC 4.3 loses location information for arg1. GCC 4.2 is OK. | |
3088 | + if { [test_compiler_info "gcc-4-3-*"] } { | |
3089 | + setup_xfail *-*-* | |
3090 | + } | |
3091 | + fail $msg | |
3092 | + } | |
3093 | + } | |
3094 | +} else { | |
3095 | + gdb_test "up" "#1 .*main .* at .*" "up from bar (2)" | |
3096 | + gdb_test "info locals" ".*arg1 = 0.*" "info locals above bar (2)" | |
3097 | +} | |
3098 | + | |
3099 | +# Make sure that locals on the stack are found. This is an array to | |
3100 | +# prevent it from living in a register. | |
3101 | +gdb_test "print array\[0\]" "\\\$$decimal = 0" "print local (2)" | |
3102 | + | |
3103 | +if { ! $no_frames } { | |
3104 | + # Verify that we do not print out variables from the inlined | |
3105 | + # function's caller. | |
3106 | + gdb_test "print val" "No symbol \"val\" in current context\\." \ | |
3107 | + "print out of scope local" | |
3108 | +} | |
3109 | + | |
3110 | +# Repeat the tests from a depth of two inlined functions, and with a | |
3111 | +# more interesting value in the local array. | |
3112 | +gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (3)" | |
3113 | +if { ! $no_frames } { | |
3114 | + gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*func2.*#3 .*main.*" \ | |
3115 | + "backtrace from bar (3)" | |
3116 | + gdb_test "up" "#1 .*func1 .* at .*" "up from bar (3)" | |
3117 | + gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (3)" | |
3118 | + gdb_test "info locals" "array = {.*}" "info locals above bar (3)" | |
3119 | + | |
3120 | + set msg "info args above bar (3)" | |
3121 | + gdb_test_multiple "info args" $msg { | |
3122 | + -re "arg1 = $decimal\r\n$gdb_prompt $" { | |
3123 | + pass $msg | |
3124 | + } | |
3125 | + -re "arg1 = <value optimized out>\r\n$gdb_prompt $" { | |
3126 | + # GCC 4.3 loses location information for arg1. GCC 4.2 is OK. | |
3127 | + if { [test_compiler_info "gcc-4-3-*"] } { | |
3128 | + setup_xfail *-*-* | |
3129 | + } | |
3130 | + fail $msg | |
3131 | + } | |
3132 | + } | |
3133 | +} else { | |
3134 | + gdb_test "up" "#1 .*main .* at .*" "up from bar (3)" | |
3135 | + gdb_test "info locals" ".*arg1 = 1.*" "info locals above bar (3a)" | |
3136 | + gdb_test "info locals" ".*arg2 = 184.*" "info locals above bar (3b)" | |
3137 | +} | |
3138 | + | |
3139 | +gdb_test "print array\[0\]" "\\\$$decimal = 184" "print local (3)" | |
d566d21e | 3140 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-markers.c |
3a58abaf AM |
3141 | =================================================================== |
3142 | --- /dev/null 1970-01-01 00:00:00.000000000 +0000 | |
d566d21e | 3143 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-markers.c 2009-03-21 21:06:17.000000000 +0100 |
3a58abaf AM |
3144 | @@ -0,0 +1,36 @@ |
3145 | +/* Copyright (C) 2008 Free Software Foundation, Inc. | |
3146 | + | |
3147 | + This program is free software; you can redistribute it and/or modify | |
3148 | + it under the terms of the GNU General Public License as published by | |
3149 | + the Free Software Foundation; either version 3 of the License, or | |
3150 | + (at your option) any later version. | |
3151 | + | |
3152 | + This program is distributed in the hope that it will be useful, | |
3153 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
3154 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
3155 | + GNU General Public License for more details. | |
3156 | + | |
3157 | + You should have received a copy of the GNU General Public License | |
3158 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
3159 | + | |
3160 | +extern int x, y; | |
3161 | + | |
3162 | +void bar(void) | |
3163 | +{ | |
3164 | + x += y; /* set breakpoint 1 here */ | |
3165 | +} | |
3166 | + | |
3167 | +void marker(void) | |
3168 | +{ | |
3169 | + x += y; /* set breakpoint 2 here */ | |
3170 | +} | |
3171 | + | |
3172 | +inline void inlined_fn(void) | |
3173 | +{ | |
3174 | + x += y; | |
3175 | +} | |
3176 | + | |
3177 | +void noinline(void) | |
3178 | +{ | |
3179 | + inlined_fn (); /* inlined */ | |
3180 | +} | |
d566d21e | 3181 | Index: gdb-6.8.50.20090302/gdb/testsuite/lib/gdb.exp |
3a58abaf | 3182 | =================================================================== |
d566d21e | 3183 | --- gdb-6.8.50.20090302.orig/gdb/testsuite/lib/gdb.exp 2009-03-21 21:06:04.000000000 +0100 |
3184 | +++ gdb-6.8.50.20090302/gdb/testsuite/lib/gdb.exp 2009-03-21 21:06:17.000000000 +0100 | |
3a58abaf AM |
3185 | @@ -1474,6 +1474,37 @@ proc skip_hp_tests {} { |
3186 | return $skip_hp | |
3187 | } | |
3188 | ||
3189 | +# Return whether we should skip tests for showing inlined functions in | |
3190 | +# backtraces. Requires get_compiler_info and get_debug_format. | |
3191 | + | |
3192 | +proc skip_inline_frame_tests {} { | |
3193 | + # GDB only recognizes inlining information in DWARF 2 (DWARF 3). | |
3194 | + if { ! [test_debug_format "DWARF 2"] } { | |
3195 | + return 1 | |
3196 | + } | |
3197 | + | |
3198 | + # GCC before 4.1 does not emit DW_AT_call_file / DW_AT_call_line. | |
3199 | + if { ([test_compiler_info "gcc-2-*"] | |
3200 | + || [test_compiler_info "gcc-3-*"] | |
3201 | + || [test_compiler_info "gcc-4-0-*"]) } { | |
3202 | + return 1 | |
3203 | + } | |
3204 | + | |
3205 | + return 0 | |
3206 | +} | |
3207 | + | |
3208 | +# Return whether we should skip tests for showing variables from | |
3209 | +# inlined functions. Requires get_compiler_info and get_debug_format. | |
3210 | + | |
3211 | +proc skip_inline_var_tests {} { | |
3212 | + # GDB only recognizes inlining information in DWARF 2 (DWARF 3). | |
3213 | + if { ! [test_debug_format "DWARF 2"] } { | |
3214 | + return 1 | |
3215 | + } | |
3216 | + | |
3217 | + return 0 | |
3218 | +} | |
3219 | + | |
3220 | set compiler_info "unknown" | |
3221 | set gcc_compiled 0 | |
3222 | set hp_cc_compiler 0 | |
d566d21e | 3223 | Index: gdb-6.8.50.20090302/gdb/valops.c |
3a58abaf | 3224 | =================================================================== |
d566d21e | 3225 | --- gdb-6.8.50.20090302.orig/gdb/valops.c 2009-03-21 21:06:03.000000000 +0100 |
3226 | +++ gdb-6.8.50.20090302/gdb/valops.c 2009-03-21 21:06:17.000000000 +0100 | |
3a58abaf AM |
3227 | @@ -1072,7 +1072,7 @@ value_of_variable (struct symbol *var, s |
3228 | frame = block_innermost_frame (b); | |
3229 | if (!frame) | |
3230 | { | |
3231 | - if (BLOCK_FUNCTION (b) | |
3232 | + if (BLOCK_FUNCTION (b) && !block_inlined_p (b) | |
3233 | && SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b))) | |
3234 | error (_("No frame is currently executing in block %s."), | |
3235 | SYMBOL_PRINT_NAME (BLOCK_FUNCTION (b))); | |
d566d21e | 3236 | Index: gdb-6.8.50.20090302/gdb/Makefile.in |
3a58abaf | 3237 | =================================================================== |
d566d21e | 3238 | --- gdb-6.8.50.20090302.orig/gdb/Makefile.in 2009-03-21 21:06:04.000000000 +0100 |
3239 | +++ gdb-6.8.50.20090302/gdb/Makefile.in 2009-03-21 21:06:17.000000000 +0100 | |
3240 | @@ -667,6 +667,7 @@ SFILES = ada-exp.y ada-lang.c ada-typepr | |
3a58abaf AM |
3241 | inf-loop.c \ |
3242 | infcall.c \ | |
3243 | infcmd.c inflow.c infrun.c \ | |
3244 | + inline-frame.c \ | |
3245 | interps.c \ | |
3246 | jv-exp.y jv-lang.c jv-valprint.c jv-typeprint.c \ | |
3247 | language.c linespec.c \ | |
d566d21e | 3248 | @@ -839,6 +840,7 @@ COMMON_OBS = $(DEPFILES) $(CONFIG_OBS) $ |
3a58abaf AM |
3249 | user-regs.o \ |
3250 | frame.o frame-unwind.o doublest.o \ | |
3251 | frame-base.o \ | |
3252 | + inline-frame.o \ | |
3253 | gnu-v2-abi.o gnu-v3-abi.o cp-abi.o cp-support.o \ | |
3254 | cp-namespace.o \ | |
3255 | reggroups.o regset.o \ | |
d566d21e | 3256 | Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/Makefile.in |
3a58abaf | 3257 | =================================================================== |
d566d21e | 3258 | --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/Makefile.in 2008-04-18 01:06:54.000000000 +0200 |
3259 | +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/Makefile.in 2009-03-21 21:06:17.000000000 +0100 | |
3a58abaf AM |
3260 | @@ -1,7 +1,7 @@ |
3261 | VPATH = @srcdir@ | |
3262 | srcdir = @srcdir@ | |
3263 | ||
3264 | -EXECUTABLES = hello/hello | |
3265 | +EXECUTABLES = clobbered-registers-O2 inline-bt inline-cmds inline-locals | |
3266 | ||
3267 | MISCELLANEOUS = | |
3268 |