gdb/gdb-6.8-inlining-addon.patch
Jan Kratochvil 3ce5394498 - Archer update to the snapshot: 837d9879980148af05eae540d92caeb7200f1813
- Archer backport: 8340d06295c8db80c544503458305197891e0348
- Fixes [master] regression for Eclipse CDT testsuite.
- Archer backport: 16328456d5740917ade0a49bcecc14c4564b9a99
- Fixes #2 [expr] compatibility with gcc-4.4 on gdb.cp/namespace-using.exp.
- Rebase [expr] on the Keith Seitz's sync with FSF GDB fixing the former
    merge.
2009-03-27 08:52:16 +00:00

714 lines
28 KiB
Diff
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

infcall.c <unwind_on_signal_p>:
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-25 22:33:02.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.c 2009-03-25 22:34:02.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/>. */
-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-25 22:33:02.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-bt.exp 2009-03-25 22:34:02.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-25 22:33:02.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.c 2009-03-25 22:34:02.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/>. */
-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-25 22:33:02.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-cmds.exp 2009-03-25 22:34:02.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-25 22:33:02.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.c 2009-03-25 22:34:02.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/>. */
-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-25 22:33:02.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-locals.exp 2009-03-25 22:34:02.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-25 22:33:02.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/frame.c 2009-03-25 22:34:02.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-25 22:33:02.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/breakpoint.c 2009-03-25 22:34:02.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. */
@@ -5169,9 +5190,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-25 22:33:02.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/inline-frame.c 2009-03-25 22:34:02.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-25 22:33:02.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/testsuite/gdb.opt/inline-markers.c 2009-03-25 22:34:02.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-25 22:33:02.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/gdbthread.h 2009-03-25 22:34:02.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-25 22:33:02.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/infcmd.c 2009-03-25 22:34:02.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-25 22:33:02.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/infrun.c 2009-03-25 22:34:02.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-25 22:26:51.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/target.c 2009-03-25 22:34:02.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-25 22:33:02.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/inline-frame.h 2009-03-25 22:34:02.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-25 22:33:02.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/infcall.c 2009-03-25 22:34:02.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-25 22:33:44.000000000 +0100
+++ gdb-6.8.50.20090302/gdb/dwarf2read.c 2009-03-25 22:34:11.000000000 +0100
@@ -3471,6 +3471,7 @@ read_func_scope (struct die_info *die, s
unsigned die_children;
struct attribute *call_line, *call_file;
int inlined_func = (die->tag == DW_TAG_inlined_subroutine);
+ struct type *type;
if (inlined_func)
{
@@ -3513,7 +3514,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. */
@@ -8751,6 +8755,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: