- Fix crash / implement `finish' into inlined functions (BZ 479781).

- Drop the gdb.threads/attach-into-signal.exp change as obsolete.
This commit is contained in:
Jan Kratochvil 2009-02-09 12:35:37 +00:00
parent c1c2c92c21
commit ec0fcb652c
2 changed files with 390 additions and 37 deletions

View File

@ -1,7 +1,7 @@
Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-bt.c
Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-bt.c
===================================================================
--- gdb-6.8.50.20081128.orig/gdb/testsuite/gdb.opt/inline-bt.c 2008-12-10 00:25:31.000000000 +0100
+++ gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-bt.c 2008-12-10 00:37:26.000000000 +0100
--- gdb-6.8.50.20081214.orig/gdb/testsuite/gdb.opt/inline-bt.c 2009-02-09 13:28:48.000000000 +0100
+++ gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-bt.c 2009-02-09 13:28:49.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 <http://www.gnu.org/licenses/>. */
@ -21,10 +21,10 @@ Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-bt.c
inline int func1(void)
{
Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-bt.exp
Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-bt.exp
===================================================================
--- gdb-6.8.50.20081128.orig/gdb/testsuite/gdb.opt/inline-bt.exp 2008-12-10 00:25:31.000000000 +0100
+++ gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-bt.exp 2008-12-10 00:37:26.000000000 +0100
--- gdb-6.8.50.20081214.orig/gdb/testsuite/gdb.opt/inline-bt.exp 2009-02-09 13:28:48.000000000 +0100
+++ gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-bt.exp 2009-02-09 13:28:49.000000000 +0100
@@ -41,18 +41,19 @@ if { [skip_inline_frame_tests] } {
return
}
@ -53,10 +53,10 @@ Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-bt.exp
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.20081128/gdb/testsuite/gdb.opt/inline-cmds.c
Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-cmds.c
===================================================================
--- gdb-6.8.50.20081128.orig/gdb/testsuite/gdb.opt/inline-cmds.c 2008-12-10 00:25:31.000000000 +0100
+++ gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-cmds.c 2008-12-10 00:37:26.000000000 +0100
--- gdb-6.8.50.20081214.orig/gdb/testsuite/gdb.opt/inline-cmds.c 2009-02-09 13:28:48.000000000 +0100
+++ gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-cmds.c 2009-02-09 13:28:49.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 <http://www.gnu.org/licenses/>. */
@ -79,11 +79,11 @@ Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-cmds.c
inline int func1(void)
{
bar ();
Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-cmds.exp
Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-cmds.exp
===================================================================
--- gdb-6.8.50.20081128.orig/gdb/testsuite/gdb.opt/inline-cmds.exp 2008-12-10 00:25:31.000000000 +0100
+++ gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-cmds.exp 2008-12-10 00:36:27.000000000 +0100
@@ -45,9 +45,9 @@ if { [skip_inline_frame_tests] } {
--- gdb-6.8.50.20081214.orig/gdb/testsuite/gdb.opt/inline-cmds.exp 2009-02-09 13:28:48.000000000 +0100
+++ gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-cmds.exp 2009-02-09 13:30:16.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.
@ -94,20 +94,89 @@ Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-cmds.exp
+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)"
@@ -66,7 +66,7 @@ gdb_test "info frame" ".*inlined into fr
-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 2 here.*" "continue to marker"
-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"
+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.
Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-locals.c
@@ -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.20081214/gdb/testsuite/gdb.opt/inline-locals.c
===================================================================
--- gdb-6.8.50.20081128.orig/gdb/testsuite/gdb.opt/inline-locals.c 2008-12-10 00:25:31.000000000 +0100
+++ gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-locals.c 2008-12-10 00:37:26.000000000 +0100
--- gdb-6.8.50.20081214.orig/gdb/testsuite/gdb.opt/inline-locals.c 2009-02-09 13:28:48.000000000 +0100
+++ gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-locals.c 2009-02-09 13:28:49.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 <http://www.gnu.org/licenses/>. */
@ -127,10 +196,10 @@ Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-locals.c
inline int func1(int arg1)
{
Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-locals.exp
Index: gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-locals.exp
===================================================================
--- gdb-6.8.50.20081128.orig/gdb/testsuite/gdb.opt/inline-locals.exp 2008-12-10 00:25:31.000000000 +0100
+++ gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-locals.exp 2008-12-10 00:37:26.000000000 +0100
--- gdb-6.8.50.20081214.orig/gdb/testsuite/gdb.opt/inline-locals.exp 2009-02-09 13:28:48.000000000 +0100
+++ gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-locals.exp 2009-02-09 13:28:49.000000000 +0100
@@ -43,8 +43,8 @@ if { [skip_inline_var_tests] } {
set no_frames [skip_inline_frame_tests]
@ -160,10 +229,10 @@ Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-locals.exp
+ setup_kfail *-*-* "gcc/debug.optimization"
+}
gdb_test "print array\[0\]" "\\\$$decimal = 184" "print local (3)"
Index: gdb-6.8.50.20081128/gdb/frame.c
Index: gdb-6.8.50.20081214/gdb/frame.c
===================================================================
--- gdb-6.8.50.20081128.orig/gdb/frame.c 2008-12-10 00:25:31.000000000 +0100
+++ gdb-6.8.50.20081128/gdb/frame.c 2008-12-10 00:25:31.000000000 +0100
--- gdb-6.8.50.20081214.orig/gdb/frame.c 2009-02-09 13:28:48.000000000 +0100
+++ gdb-6.8.50.20081214/gdb/frame.c 2009-02-09 13:30:16.000000000 +0100
@@ -269,7 +269,7 @@ fprint_frame (struct ui_file *file, stru
static struct frame_info *
skip_inlined_frames (struct frame_info *frame)
@ -173,10 +242,37 @@ Index: gdb-6.8.50.20081128/gdb/frame.c
frame = get_prev_frame (frame);
return frame;
Index: gdb-6.8.50.20081128/gdb/breakpoint.c
@@ -1697,6 +1697,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;
@@ -1739,6 +1740,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;
@@ -1770,7 +1774,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.20081214/gdb/breakpoint.c
===================================================================
--- gdb-6.8.50.20081128.orig/gdb/breakpoint.c 2008-12-10 00:25:31.000000000 +0100
+++ gdb-6.8.50.20081128/gdb/breakpoint.c 2008-12-10 00:36:27.000000000 +0100
--- gdb-6.8.50.20081214.orig/gdb/breakpoint.c 2009-02-09 13:28:48.000000000 +0100
+++ gdb-6.8.50.20081214/gdb/breakpoint.c 2009-02-09 13:30:16.000000000 +0100
@@ -57,6 +57,7 @@
#include "top.h"
#include "wrapper.h"
@ -185,7 +281,36 @@ Index: gdb-6.8.50.20081128/gdb/breakpoint.c
#include "mi/mi-common.h"
@@ -2976,6 +2977,12 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
@@ -2833,10 +2834,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;
@@ -2975,6 +2990,12 @@ bpstat_stop_status (CORE_ADDR bp_addr, p
bs->print = 0;
}
bs->commands = copy_command_lines (bs->commands);
@ -198,10 +323,23 @@ Index: gdb-6.8.50.20081128/gdb/breakpoint.c
}
/* Print nothing for this entry if we dont stop or if we dont print. */
Index: gdb-6.8.50.20081128/gdb/inline-frame.c
@@ -4826,9 +4847,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.20081214/gdb/inline-frame.c
===================================================================
--- gdb-6.8.50.20081128.orig/gdb/inline-frame.c 2008-12-10 00:25:31.000000000 +0100
+++ gdb-6.8.50.20081128/gdb/inline-frame.c 2008-12-10 00:40:49.000000000 +0100
--- gdb-6.8.50.20081214.orig/gdb/inline-frame.c 2009-02-09 13:28:48.000000000 +0100
+++ gdb-6.8.50.20081214/gdb/inline-frame.c 2009-02-09 13:30:16.000000000 +0100
@@ -183,6 +183,12 @@ inline_frame_sniffer (const struct frame
if (frame_block == NULL)
return 0;
@ -254,10 +392,34 @@ Index: gdb-6.8.50.20081128/gdb/inline-frame.c
if (skip_count != 0)
reinit_frame_cache ();
Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-markers.c
@@ -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.20081214/gdb/testsuite/gdb.opt/inline-markers.c
===================================================================
--- gdb-6.8.50.20081128.orig/gdb/testsuite/gdb.opt/inline-markers.c 2008-12-10 00:25:31.000000000 +0100
+++ gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-markers.c 2008-12-10 00:37:26.000000000 +0100
--- gdb-6.8.50.20081214.orig/gdb/testsuite/gdb.opt/inline-markers.c 2009-02-09 13:28:48.000000000 +0100
+++ gdb-6.8.50.20081214/gdb/testsuite/gdb.opt/inline-markers.c 2009-02-09 13:28:49.000000000 +0100
@@ -15,11 +15,6 @@
extern int x, y;
@ -270,3 +432,192 @@ Index: gdb-6.8.50.20081128/gdb/testsuite/gdb.opt/inline-markers.c
void marker(void)
{
x += y; /* set breakpoint 2 here */
Index: gdb-6.8.50.20081214/gdb/gdbthread.h
===================================================================
--- gdb-6.8.50.20081214.orig/gdb/gdbthread.h 2009-02-09 13:28:48.000000000 +0100
+++ gdb-6.8.50.20081214/gdb/gdbthread.h 2009-02-09 13:30:16.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.20081214/gdb/infcmd.c
===================================================================
--- gdb-6.8.50.20081214.orig/gdb/infcmd.c 2009-02-09 13:28:48.000000000 +0100
+++ gdb-6.8.50.20081214/gdb/infcmd.c 2009-02-09 13:30:16.000000000 +0100
@@ -1373,11 +1373,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);
}
@@ -1481,6 +1481,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;
@@ -1504,7 +1514,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;
@@ -1535,46 +1547,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. */
@@ -1588,10 +1617,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.20081214/gdb/infrun.c
===================================================================
--- gdb-6.8.50.20081214.orig/gdb/infrun.c 2009-02-09 13:29:51.000000000 +0100
+++ gdb-6.8.50.20081214/gdb/infrun.c 2009-02-09 13:30:16.000000000 +0100
@@ -1201,6 +1201,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.20081214/gdb/inline-frame.h
===================================================================
--- gdb-6.8.50.20081214.orig/gdb/inline-frame.h 2009-02-09 13:28:48.000000000 +0100
+++ gdb-6.8.50.20081214/gdb/inline-frame.h 2009-02-09 13:30:16.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. */

View File

@ -13,7 +13,7 @@ Version: 6.8.50.20081214
# The release always contains a leading reserved number, start it at 1.
# `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
Release: 1%{?_with_upstream:.upstream}%{?dist}
Release: 2%{?_with_upstream:.upstream}%{?dist}
License: GPLv3+
Group: Development/Debuggers
@ -834,6 +834,8 @@ fi
%endif
%changelog
* Mon Feb 9 2009 Jan Kratochvil <jan.kratochvil@redhat.com> - 6.8.50.20081214-2
- Fix crash / implement `finish' into inlined functions (BZ 479781).
- Drop the gdb.threads/attach-into-signal.exp change as obsolete.
* Sun Dec 14 2008 Jan Kratochvil <jan.kratochvil@redhat.com> - 6.8.50.20081214-1