infcall.c : Revert the change of: gdb-6.8-inlining.patch causing: FAIL: gdb.base/unwindonsignal.exp: unwindonsignal, stack unwound resume() -> target_resume() move of clear_inline_frame_state() is for: gdb.mi/mi-nsmoribund.exp Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.c =================================================================== --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-bt.c 2009-03-06 19:07:30.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.c 2009-03-06 19:07:30.000000000 +0100 @@ -13,10 +13,16 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -int x, y; +/* VOLATILE forces all the inlining to happen as otherwise the whole program + gets optimized by CSE to just simple assignments of the results. */ +volatile int x, y; volatile int result; -void bar(void); +inline void bar(void) +{ + x += y; /* set breakpoint 1 here */ +} + inline int func1(void) { Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.exp =================================================================== --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-bt.exp 2009-03-06 19:07:30.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.exp 2009-03-06 19:07:30.000000000 +0100 @@ -41,18 +41,19 @@ if { [skip_inline_frame_tests] } { return } -set line1 [gdb_get_line_number "set breakpoint 1 here" ${fullsrcfile2}] -gdb_breakpoint $srcfile2:$line1 +set line1 [gdb_get_line_number "set breakpoint 1 here" ${srcfile}] +gdb_breakpoint $srcfile:$line1 gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (1)" gdb_test "backtrace" "#0 bar.*#1 .*main.*" "backtrace from bar (1)" -gdb_test "info frame" ".*called by frame.*" "bar not inlined" +gdb_test "info frame" ".*inlined into frame.*" "bar inlined" -gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (2)" -gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*main.*" \ - "backtrace from bar (2)" -gdb_test "up" "#1 .*func1.*" "up from bar (2)" -gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (2)" +# gcc-4.3.1 omits the line number information for (2). +#gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (2)" +#gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*main.*" \ +# "backtrace from bar (2)" +#gdb_test "up" "#1 .*func1.*" "up from bar (2)" +#gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (2)" gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (3)" gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*func2.*#3 .*main.*" \ Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.c =================================================================== --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-cmds.c 2009-03-06 19:07:30.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.c 2009-03-06 19:07:30.000000000 +0100 @@ -13,13 +13,19 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -int x, y; +/* VOLATILE forces all the inlining to happen as otherwise the whole program + gets optimized by CSE to just simple assignments of the results. */ +volatile int x, y; volatile int result; -void bar(void); void marker(void); void noinline(void); +inline void bar(void) +{ + x += y; /* set breakpoint 1 here */ +} + inline int func1(void) { bar (); Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.exp =================================================================== --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-cmds.exp 2009-03-06 19:07:30.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.exp 2009-03-06 19:07:30.000000000 +0100 @@ -45,28 +45,28 @@ if { [skip_inline_frame_tests] } { # First, check that the things we expected to be inlined really were, # and those that shouldn't be weren't. -set line1 [gdb_get_line_number "set breakpoint 1 here" ${fullsrcfile2}] +set line1 [gdb_get_line_number "set breakpoint 1 here" ${srcfile2}] gdb_breakpoint $srcfile2:$line1 -set line2 [gdb_get_line_number "set breakpoint 2 here" ${fullsrcfile2}] +set line2 [gdb_get_line_number "set breakpoint 2 here" ${srcfile2}] gdb_breakpoint $srcfile2:$line2 -gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (1)" +gdb_test "continue" "set breakpoint 1 here.*" "continue to bar (1)" gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*main.*" \ "backtrace from bar (1)" gdb_test "up" "#1 .*func1.*" "up from bar (1)" -gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (1)" +gdb_test "info frame" "inlined into frame.*" "func1 inlined (1)" -gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (2)" +gdb_test "continue" "set breakpoint 1 here.*" "continue to bar (2)" gdb_test "backtrace" "#0 bar.*#1 .*func1.*#2 .*func2.*#3 .*main.*" \ "backtrace from bar (2)" gdb_test "up" "#1 .*func1.*" "up from bar (2)" -gdb_test "info frame" ".*inlined into frame.*" "func1 inlined (2)" +gdb_test "info frame" "inlined into frame.*" "func1 inlined (2)" gdb_test "up" "#2 .*func2.*" "up from func1 (2)" -gdb_test "info frame" ".*inlined into frame.*" "func2 inlined (2)" +gdb_test "info frame" "inlined into frame.*" "func2 inlined (2)" -gdb_test "continue" ".*set breakpoint 2 here.*" "continue to marker" +gdb_test "continue" "set breakpoint 2 here.*" "continue to marker" gdb_test "backtrace" "#0 marker.*#1 .*main.*" "backtrace from marker" -gdb_test "info frame" ".*called by frame.*" "marker not inlined" +gdb_test "info frame" "\n called by frame.*" "marker not inlined" # Next, check that we can next over inlined functions. We should not end up # inside any of them. @@ -201,7 +201,7 @@ set line3 [gdb_get_line_number "set brea gdb_breakpoint $line3 gdb_continue_to_breakpoint "consecutive func1" -gdb_test "next" ".*func1 .*first call.*" "next to first func1" +gdb_test "next" "func1 .*first call.*" "next to first func1" set msg "next to second func1" gdb_test_multiple "next" $msg { -re ".*func1 .*second call.*$gdb_prompt $" { @@ -224,16 +224,16 @@ set line4 [gdb_get_line_number "set brea gdb_breakpoint $line4 gdb_continue_to_breakpoint "func1 then func3" -gdb_test "next" ".*func1 \\\(\\\);" "next to func1 before func3" -gdb_test "next" ".*func3 \\\(\\\);" "next to func3" +gdb_test "next" "func1 \\\(\\\);" "next to func1 before func3" +gdb_test "next" "func3 \\\(\\\);" "next to func3" # Test finishing out of one thing and into another. set line5 [gdb_get_line_number "set breakpoint 5 here"] gdb_breakpoint $line5 gdb_continue_to_breakpoint "finish into func1" -gdb_test "next" ".*marker \\\(\\\);" "next to finish marker" -gdb_test "step" ".*set breakpoint 2 here.*" "step into finish marker" +gdb_test "next" "marker \\\(\\\);" "next to finish marker" +gdb_test "step" "set breakpoint 2 here.*" "step into finish marker" gdb_test "finish" "func1 \\\(\\\);" "finish from marker to func1" gdb_test "step" "bar \\\(\\\);" "step into func1 for finish" @@ -268,12 +268,12 @@ gdb_test "step" "noinline \\\(\\\) at .* gdb_test "bt" "#0 noinline.*#1 .*outer_inline1.*#2 .*outer_inline2.*#3 main.*" "backtrace at noinline from outer_inline1" gdb_test "step" "inlined_fn \\\(\\\) at .*" "enter inlined_fn from noinline" gdb_test "bt" "#0 inlined_fn.*#1 noinline.*#2 .*outer_inline1.*#3 .*outer_inline2.*#4 main.*" "backtrace at inlined_fn from noinline" -gdb_test "info frame" ".*inlined into frame.*" "inlined_fn from noinline inlined" -gdb_test "up" "#1 noinline.*" "up to noinline" -gdb_test "info frame" ".*\n called by frame.*" "noinline from outer_inline1 not inlined" -gdb_test "up" "#2 .*outer_inline1.*" "up to outer_inline1" -gdb_test "info frame" ".*inlined into frame.*" "outer_inline1 inlined" -gdb_test "up" "#3 .*outer_inline2.*" "up to outer_inline2" -gdb_test "info frame" ".*inlined into frame.*" "outer_inline2 inlined" -gdb_test "up" "#4 main.*" "up from outer_inline2" -gdb_test "info frame" ".*\n caller of frame.*" "main not inlined" +gdb_test "info frame" "inlined into frame.*" "inlined_fn from noinline inlined" +gdb_test "fini" "" "up to noinline" +gdb_test "info frame" "\n called by frame.*" "noinline from outer_inline1 not inlined" +gdb_test "fini" "" "up to outer_inline1" +gdb_test "info frame" "inlined into frame.*" "outer_inline1 inlined" +gdb_test "fini" "" "up to outer_inline2" +gdb_test "info frame" "inlined into frame.*" "outer_inline2 inlined" +gdb_test "fini" "" "up from outer_inline2" +gdb_test "info frame" " in main \[^\n\]*\n source language.*" "main not inlined" Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.c =================================================================== --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-locals.c 2009-03-06 19:07:30.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.c 2009-03-06 19:07:30.000000000 +0100 @@ -13,11 +13,16 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -int x, y; +/* VOLATILE forces all the inlining to happen as otherwise the whole program + gets optimized by CSE to just simple assignments of the results. */ +volatile int x, y; volatile int result; volatile int *array_p; -void bar(void); +inline void bar(void) +{ + x += y; /* set breakpoint 1 here */ +} inline int func1(int arg1) { Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.exp =================================================================== --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-locals.exp 2009-03-06 19:07:30.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.exp 2009-03-06 19:07:30.000000000 +0100 @@ -43,8 +43,8 @@ if { [skip_inline_var_tests] } { set no_frames [skip_inline_frame_tests] -set line1 [gdb_get_line_number "set breakpoint 1 here" ${fullsrcfile2}] -gdb_breakpoint $srcfile2:$line1 +set line1 [gdb_get_line_number "set breakpoint 1 here" ${srcfile}] +gdb_breakpoint $srcfile:$line1 gdb_test "continue" ".*set breakpoint 1 here.*" "continue to bar (1)" @@ -77,6 +77,9 @@ if { ! $no_frames } { # Make sure that locals on the stack are found. This is an array to # prevent it from living in a register. +if [test_compiler_info "gcc-4-3-*"] { + setup_kfail *-*-* "gcc/debug.optimization" +} gdb_test "print array\[0\]" "\\\$$decimal = 0" "print local (2)" if { ! $no_frames } { @@ -115,4 +118,7 @@ if { ! $no_frames } { gdb_test "info locals" ".*arg2 = 184.*" "info locals above bar (3b)" } +if [test_compiler_info "gcc-4-3-*"] { + setup_kfail *-*-* "gcc/debug.optimization" +} gdb_test "print array\[0\]" "\\\$$decimal = 184" "print local (3)" Index: gdb-6.8.50.20090302/gdb/frame.c =================================================================== --- gdb-6.8.50.20090302.orig/gdb/frame.c 2009-03-06 19:07:30.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/frame.c 2009-03-06 19:07:30.000000000 +0100 @@ -269,7 +269,7 @@ fprint_frame (struct ui_file *file, stru static struct frame_info * skip_inlined_frames (struct frame_info *frame) { - while (get_frame_type (frame) == INLINE_FRAME) + while (frame && get_frame_type (frame) == INLINE_FRAME) frame = get_prev_frame (frame); return frame; @@ -1670,6 +1670,7 @@ get_frame_address_in_block (struct frame { /* A draft address. */ CORE_ADDR pc = get_frame_pc (this_frame); + struct thread_info *tp = inferior_thread (); struct frame_info *next_frame = this_frame->next; @@ -1712,6 +1713,9 @@ get_frame_address_in_block (struct frame while in an inlined function, then the code address of the "calling" normal function should not be adjusted either. */ + if (tp->current_pc_is_notcurrent) + return pc - 1; + while (get_frame_type (next_frame) == INLINE_FRAME) next_frame = next_frame->next; @@ -1743,7 +1747,7 @@ find_frame_sal (struct frame_info *frame sym = inline_skipped_symbol (inferior_ptid); init_sal (sal); - if (SYMBOL_LINE (sym) != 0) + if (sym != NULL && SYMBOL_LINE (sym) != 0) { sal->symtab = SYMBOL_SYMTAB (sym); sal->line = SYMBOL_LINE (sym); Index: gdb-6.8.50.20090302/gdb/breakpoint.c =================================================================== --- gdb-6.8.50.20090302.orig/gdb/breakpoint.c 2009-03-06 19:07:30.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/breakpoint.c 2009-03-06 19:07:30.000000000 +0100 @@ -57,6 +57,7 @@ #include "top.h" #include "wrapper.h" #include "valprint.h" +#include "inline-frame.h" #include "mi/mi-common.h" @@ -2902,10 +2903,24 @@ bpstat_check_breakpoint_conditions (bpst const struct bp_location *bl = bs->breakpoint_at; struct breakpoint *b = bl->owner; - if (frame_id_p (b->frame_id) - && !frame_id_eq (b->frame_id, get_stack_frame_id (get_current_frame ()))) - bs->stop = 0; - else if (bs->stop) + if (frame_id_p (b->frame_id)) + { + struct frame_info *b_frame, *frame; + struct frame_id b_frame_id, current_frame_id; + + b_frame = frame_find_by_id (b->frame_id); + + /* get_stack_frame_id normalizes the id to the real non-inlined function + by skip_inlined_frames. */ + b_frame_id = get_stack_frame_id (b_frame); + current_frame_id = get_stack_frame_id (get_current_frame ()); + + /* Completely different (inlining notwithstanding) frames? */ + if (!frame_id_eq (b_frame_id, current_frame_id)) + bs->stop = 0; + } + + if (bs->stop) { int value_is_zero = 0; @@ -3044,6 +3059,12 @@ bpstat_stop_status (CORE_ADDR bp_addr, p bs->print = 0; } bs->commands = copy_command_lines (bs->commands); + + /* Display the innermost inlined frame at a breakpont as it gives to + most of the available information. */ + if (b->type != bp_until && b->type != bp_finish) + while (inline_skipped_frames (ptid)) + step_into_inline_frame (ptid); } /* Print nothing for this entry if we dont stop or if we dont print. */ @@ -5168,9 +5189,9 @@ set_momentary_breakpoint (struct symtab_ { struct breakpoint *b; - /* If FRAME_ID is valid, it should be a real frame, not an inlined - one. */ - gdb_assert (!frame_id_inlined_p (frame_id)); + /* We can be returning even into an inline frame. While finish_command will + shortcut the case of returning _from_ an inline frame we still may be + returning from non-inlined frame _to_ an inlined frame. */ b = set_raw_breakpoint (sal, type); b->enable_state = bp_enabled; Index: gdb-6.8.50.20090302/gdb/inline-frame.c =================================================================== --- gdb-6.8.50.20090302.orig/gdb/inline-frame.c 2009-03-06 19:07:30.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/inline-frame.c 2009-03-06 19:07:30.000000000 +0100 @@ -183,6 +183,12 @@ inline_frame_sniffer (const struct frame if (frame_block == NULL) return 0; + /* For >=2 inlined functions SKIPPED_SYMBOL needs to be different after each + step_into_inline_frame call. But skip_inline_frames is called only once + and thus SKIPPED_SYMBOL needs to be calculated by INLINE_FRAME_SNIFFER. */ + if (state) + state->skipped_symbol = NULL; + /* Calculate DEPTH, the number of inlined functions at this location. */ depth = 0; @@ -192,6 +198,10 @@ inline_frame_sniffer (const struct frame if (block_inlined_p (cur_block)) depth++; + if (state && depth == state->skipped_frames + && state->skipped_symbol == NULL) + state->skipped_symbol = BLOCK_FUNCTION (cur_block); + cur_block = BLOCK_SUPERBLOCK (cur_block); } @@ -275,7 +285,6 @@ skip_inline_frames (ptid_t ptid) { CORE_ADDR this_pc; struct block *frame_block, *cur_block; - struct symbol *last_sym = NULL; int skip_count = 0; struct inline_state *state; @@ -296,10 +305,7 @@ skip_inline_frames (ptid_t ptid) of BLOCK_START. */ if (BLOCK_START (cur_block) == this_pc || block_starting_point_at (this_pc, cur_block)) - { - skip_count++; - last_sym = BLOCK_FUNCTION (cur_block); - } + skip_count++; else break; } @@ -311,7 +317,6 @@ skip_inline_frames (ptid_t ptid) state = allocate_inline_frame_state (ptid); state->skipped_frames = skip_count; state->saved_pc = this_pc; - state->skipped_symbol = last_sym; if (skip_count != 0) reinit_frame_cache (); @@ -329,6 +334,23 @@ step_into_inline_frame (ptid_t ptid) reinit_frame_cache (); } +/* Step out of an inlined function by hiding it. */ + +void +step_out_of_inline_frame (ptid_t ptid) +{ + struct inline_state *state = find_inline_frame_state (ptid); + + gdb_assert (state != NULL); + + /* Simulate the caller adjustment. */ + if (state->skipped_frames == 0) + state->saved_pc--; + + state->skipped_frames++; + reinit_frame_cache (); +} + /* Return the number of hidden functions inlined into the current frame. */ Index: gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-markers.c =================================================================== --- gdb-6.8.50.20090302.orig/gdb/testsuite/gdb.opt/inline-markers.c 2009-03-06 19:07:30.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-markers.c 2009-03-06 19:07:30.000000000 +0100 @@ -15,11 +15,6 @@ extern int x, y; -void bar(void) -{ - x += y; /* set breakpoint 1 here */ -} - void marker(void) { x += y; /* set breakpoint 2 here */ Index: gdb-6.8.50.20090302/gdb/gdbthread.h =================================================================== --- gdb-6.8.50.20090302.orig/gdb/gdbthread.h 2009-03-06 19:07:30.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/gdbthread.h 2009-03-06 19:07:30.000000000 +0100 @@ -180,6 +180,12 @@ struct thread_info /* Private data used by the target vector implementation. */ struct private_thread_info *private; + + /* Nonzero if the current frame PC should be unwound as the caller. It is + used to keep the backtrace upper levels existing after finish_command into + an inlined frame if the current inlined function/block was ending at the + current PC. */ + int current_pc_is_notcurrent; }; /* Create an empty thread list, or empty the existing one. */ Index: gdb-6.8.50.20090302/gdb/infcmd.c =================================================================== --- gdb-6.8.50.20090302.orig/gdb/infcmd.c 2009-03-06 19:07:30.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/infcmd.c 2009-03-06 19:07:30.000000000 +0100 @@ -1391,11 +1391,11 @@ finish_command_continuation (void *arg) struct type *value_type; value_type = TYPE_TARGET_TYPE (SYMBOL_TYPE (a->function)); - if (!value_type) + if (!SYMBOL_INLINED (a->function) && !value_type) internal_error (__FILE__, __LINE__, _("finish_command: function has no target type")); - if (TYPE_CODE (value_type) != TYPE_CODE_VOID) + if (value_type && TYPE_CODE (value_type) != TYPE_CODE_VOID) print_return_value (SYMBOL_TYPE (a->function), value_type); } @@ -1499,6 +1499,16 @@ finish_forward (struct symbol *function, old_chain = make_cleanup_delete_breakpoint (breakpoint); + /* We should _always_ set CURRENT_PC_IS_NOTCURRENT here to always see the + calling line with the message `Value returned is ...'. Currently it is + seen only if at least one instruction is on that source line after the + call instruction. We would also need to hook step_once and only clear + CURRENT_PC_IS_NOTCURRENT on the first step. But it would be a change of + general non-inlining behavior against upstream. */ + + if (get_frame_type (frame) == INLINE_FRAME) + tp->current_pc_is_notcurrent = 1; + tp->proceed_to_finish = 1; /* We want stop_registers, please... */ make_cleanup_restore_integer (&suppress_stop_observer); suppress_stop_observer = 1; @@ -1522,7 +1532,9 @@ finish_forward (struct symbol *function, static void finish_command (char *arg, int from_tty) { - struct frame_info *frame; + /* FIXME: Rename `current_frame' to `frame' upon a merge. */ + struct frame_info *current_frame, *prev_frame; + CORE_ADDR frame_pc; struct symbol *function; int async_exec = 0; @@ -1553,46 +1565,63 @@ finish_command (char *arg, int from_tty) if (!target_has_execution) error (_("The program is not running.")); - frame = get_prev_frame (get_selected_frame (_("No selected frame."))); - if (frame == 0) + current_frame = get_selected_frame (_("No selected frame.")); + frame_pc = get_frame_pc (current_frame); + prev_frame = get_prev_frame (current_frame); + if (prev_frame == 0) error (_("\"finish\" not meaningful in the outermost frame.")); - clear_proceed_status (); - /* Finishing from an inline frame is completely different. We don't try to show the "return value" - no way to locate it. So we do not need a completion. */ - if (get_frame_type (get_selected_frame (_("No selected frame."))) - == INLINE_FRAME) + if (get_frame_type (current_frame) == INLINE_FRAME) { struct thread_info *tp = inferior_thread (); - - /* Claim we are stepping in the calling frame. An empty step - range means that we will stop once we aren't in a function - called by that frame. We don't use the magic "1" value for - step_range_end, because then infrun will think this is nexti, - and not step over the rest of this inlined function call. */ struct symtab_and_line empty_sal; - init_sal (&empty_sal); - set_step_info (tp, frame, empty_sal); - tp->step_range_start = tp->step_range_end = get_frame_pc (frame); - tp->step_over_calls = STEP_OVER_ALL; + struct block *frame_block; /* Print info on the selected frame, including level number but not source. */ if (from_tty) { printf_filtered (_("Run till exit from ")); - print_stack_frame (get_selected_frame (NULL), 1, LOCATION); + print_stack_frame (current_frame, 1, LOCATION); } + /* Even just a single stepi would get us out of the caller function PC + range. */ + + frame_block = get_frame_block (current_frame, NULL); + + /* FRAME_BLOCK must be initialized and also the frame printing above must + be done still with the original CURRENT_PC_IS_NOTCURRENT setting. */ + clear_proceed_status (); + + if (frame_block && BLOCK_END (frame_block) == frame_pc) + { + step_out_of_inline_frame (tp->ptid); + tp->current_pc_is_notcurrent = 1; + normal_stop (); + return; + } + + /* Claim we are stepping in the calling frame. An empty step + range means that we will stop once we aren't in a function + called by that frame. We don't use the magic "1" value for + step_range_end, because then infrun will think this is nexti, + and not step over the rest of this inlined function call. */ + init_sal (&empty_sal); + set_step_info (tp, prev_frame, empty_sal); + tp->step_range_start = tp->step_range_end = get_frame_pc (prev_frame); + tp->step_over_calls = STEP_OVER_ALL; + proceed ((CORE_ADDR) -1, TARGET_SIGNAL_DEFAULT, 1); return; } /* Find the function we will return from. */ - function = find_pc_function (get_frame_pc (get_selected_frame (NULL))); + function = find_pc_function (frame_pc); /* Print info on the selected frame, including level number but not source. */ @@ -1606,10 +1635,14 @@ finish_command (char *arg, int from_tty) print_stack_frame (get_selected_frame (NULL), 1, LOCATION); } + /* Frames printing above must be done still with the original + CURRENT_PC_IS_NOTCURRENT setting. */ + clear_proceed_status (); + if (execution_direction == EXEC_REVERSE) finish_backward (function); else - finish_forward (function, frame); + finish_forward (function, prev_frame); } Index: gdb-6.8.50.20090302/gdb/infrun.c =================================================================== --- gdb-6.8.50.20090302.orig/gdb/infrun.c 2009-03-06 19:07:30.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/infrun.c 2009-03-06 19:07:30.000000000 +0100 @@ -1152,8 +1152,6 @@ a command like `return' or `jump' to con step = 0; } - clear_inline_frame_state (resume_ptid); - if (debug_displaced && use_displaced_stepping (gdbarch) && tp->trap_expected) @@ -1205,6 +1203,8 @@ clear_proceed_status_thread (struct thre /* Discard any remaining commands or status from previous stop. */ bpstat_clear (&tp->stop_bpstat); + + tp->current_pc_is_notcurrent = 0; } static int Index: gdb-6.8.50.20090302/gdb/target.c =================================================================== --- gdb-6.8.50.20090302.orig/gdb/target.c 2009-03-06 19:07:26.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/target.c 2009-03-06 19:07:30.000000000 +0100 @@ -41,6 +41,7 @@ #include "target-descriptions.h" #include "gdbthread.h" #include "solib.h" +#include "inline-frame.h" static void target_info (char *, int); @@ -1925,6 +1926,7 @@ target_resume (ptid_t ptid, int step, en { struct target_ops *t; + clear_inline_frame_state (ptid); dcache_invalidate (target_dcache); for (t = current_target.beneath; t != NULL; t = t->beneath) Index: gdb-6.8.50.20090302/gdb/inline-frame.h =================================================================== --- gdb-6.8.50.20090302.orig/gdb/inline-frame.h 2009-03-06 19:07:30.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/inline-frame.h 2009-03-06 19:07:30.000000000 +0100 @@ -43,6 +43,10 @@ void clear_inline_frame_state (ptid_t pt void step_into_inline_frame (ptid_t ptid); +/* Step out of an inlined function by hiding it. */ + +void step_out_of_inline_frame (ptid_t ptid); + /* Return the number of hidden functions inlined into the current frame. */ Index: gdb-6.8.50.20090302/gdb/infcall.c =================================================================== --- gdb-6.8.50.20090302.orig/gdb/infcall.c 2009-03-06 19:07:30.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/infcall.c 2009-03-06 19:07:30.000000000 +0100 @@ -898,8 +898,15 @@ The program being debugged exited while if (unwind_on_signal_p) { - /* The user wants the context restored. Calling error will - run inf_status_cleanup, which does all the work. */ + /* The user wants the context restored. */ + + /* We must get back to the frame we were before the + dummy call. */ + dummy_frame_pop (dummy_id); + + /* We also need to restore inferior status to that before the + dummy call. */ + restore_inferior_status (inf_status); /* FIXME: Insert a bunch of wrap_here; name can be very long if it's a C++ name with arguments and stuff. */ Index: gdb-6.8.50.20090302/gdb/dwarf2read.c =================================================================== --- gdb-6.8.50.20090302.orig/gdb/dwarf2read.c 2009-03-06 19:07:30.000000000 +0100 +++ gdb-6.8.50.20090302/gdb/dwarf2read.c 2009-03-06 19:07:40.000000000 +0100 @@ -3463,6 +3463,7 @@ read_func_scope (struct die_info *die, s unsigned die_children = 0; struct attribute *call_line, *call_file; int inlined_func = (die->tag == DW_TAG_inlined_subroutine); + struct type *type; if (inlined_func) { @@ -3504,7 +3505,10 @@ read_func_scope (struct die_info *die, s add_to_cu_func_list (name, lowpc, highpc, cu); new = push_context (0, lowpc); - new->name = new_symbol (die, read_type_die (die, cu), cu); + type = read_type_die (die, cu); + gdb_assert (type != NULL); + new->name = new_symbol (die, type, cu); + gdb_assert (TYPE_CODE (SYMBOL_TYPE (new->name)) == TYPE_CODE_FUNC); /* If there is a location expression for DW_AT_frame_base, record it. */ @@ -8746,6 +8750,7 @@ read_type_die (struct die_info *die, str break; case DW_TAG_subprogram: case DW_TAG_subroutine_type: + case DW_TAG_inlined_subroutine: this_type = read_subroutine_type (die, cu); break; case DW_TAG_array_type: