2009-02-11 00:04:48 +00:00
|
|
|
|
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
|
|
|
|
|
|
2010-01-16 22:32:10 +00:00
|
|
|
|
Index: gdb-7.0.50.20100115/gdb/testsuite/gdb.opt/inline-bt.c
|
2008-12-14 14:05:20 +00:00
|
|
|
|
===================================================================
|
2010-01-16 22:32:10 +00:00
|
|
|
|
--- gdb-7.0.50.20100115.orig/gdb/testsuite/gdb.opt/inline-bt.c 2010-01-01 08:32:04.000000000 +0100
|
|
|
|
|
+++ gdb-7.0.50.20100115/gdb/testsuite/gdb.opt/inline-bt.c 2010-01-15 11:50:59.000000000 +0100
|
2008-12-14 14:05:20 +00:00
|
|
|
|
@@ -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)
|
|
|
|
|
{
|
2010-01-16 22:32:10 +00:00
|
|
|
|
Index: gdb-7.0.50.20100115/gdb/testsuite/gdb.opt/inline-cmds.c
|
2008-12-14 14:05:20 +00:00
|
|
|
|
===================================================================
|
2010-01-16 22:32:10 +00:00
|
|
|
|
--- gdb-7.0.50.20100115.orig/gdb/testsuite/gdb.opt/inline-cmds.c 2010-01-01 08:32:04.000000000 +0100
|
|
|
|
|
+++ gdb-7.0.50.20100115/gdb/testsuite/gdb.opt/inline-cmds.c 2010-01-15 11:50:59.000000000 +0100
|
2008-12-14 14:05:20 +00:00
|
|
|
|
@@ -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 ();
|
2010-01-16 22:32:10 +00:00
|
|
|
|
Index: gdb-7.0.50.20100115/gdb/testsuite/gdb.opt/inline-cmds.exp
|
2008-12-14 14:05:20 +00:00
|
|
|
|
===================================================================
|
2010-01-16 22:32:10 +00:00
|
|
|
|
--- gdb-7.0.50.20100115.orig/gdb/testsuite/gdb.opt/inline-cmds.exp 2010-01-01 08:32:04.000000000 +0100
|
|
|
|
|
+++ gdb-7.0.50.20100115/gdb/testsuite/gdb.opt/inline-cmds.exp 2010-01-15 11:50:59.000000000 +0100
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -230,7 +230,7 @@ set line3 [gdb_get_line_number "set brea
|
2009-02-09 12:35:37 +00:00
|
|
|
|
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 $" {
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -253,16 +253,16 @@ set line4 [gdb_get_line_number "set brea
|
2009-02-09 12:35:37 +00:00
|
|
|
|
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"
|
2009-08-04 05:37:29 +00:00
|
|
|
|
@@ -297,12 +297,12 @@ gdb_test "step" "noinline \\\(\\\) at .*
|
2009-02-09 12:35:37 +00:00
|
|
|
|
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"
|
2010-01-16 22:32:10 +00:00
|
|
|
|
Index: gdb-7.0.50.20100115/gdb/testsuite/gdb.opt/inline-locals.c
|
2008-12-14 14:05:20 +00:00
|
|
|
|
===================================================================
|
2010-01-16 22:32:10 +00:00
|
|
|
|
--- gdb-7.0.50.20100115.orig/gdb/testsuite/gdb.opt/inline-locals.c 2010-01-01 08:32:04.000000000 +0100
|
|
|
|
|
+++ gdb-7.0.50.20100115/gdb/testsuite/gdb.opt/inline-locals.c 2010-01-15 11:50:59.000000000 +0100
|
2008-12-14 14:05:20 +00:00
|
|
|
|
@@ -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)
|
|
|
|
|
{
|
2010-01-16 22:32:10 +00:00
|
|
|
|
Index: gdb-7.0.50.20100115/gdb/testsuite/gdb.opt/inline-locals.exp
|
2008-12-14 14:05:20 +00:00
|
|
|
|
===================================================================
|
2010-01-16 22:32:10 +00:00
|
|
|
|
--- gdb-7.0.50.20100115.orig/gdb/testsuite/gdb.opt/inline-locals.exp 2010-01-01 08:32:04.000000000 +0100
|
|
|
|
|
+++ gdb-7.0.50.20100115/gdb/testsuite/gdb.opt/inline-locals.exp 2010-01-15 11:50:59.000000000 +0100
|
2008-12-14 14:05:20 +00:00
|
|
|
|
@@ -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)"
|
2010-01-16 22:32:10 +00:00
|
|
|
|
Index: gdb-7.0.50.20100115/gdb/frame.c
|
2008-12-14 14:05:20 +00:00
|
|
|
|
===================================================================
|
2010-01-16 22:32:10 +00:00
|
|
|
|
--- gdb-7.0.50.20100115.orig/gdb/frame.c 2010-01-15 03:22:14.000000000 +0100
|
|
|
|
|
+++ gdb-7.0.50.20100115/gdb/frame.c 2010-01-15 11:50:59.000000000 +0100
|
|
|
|
|
@@ -316,7 +316,7 @@ fprint_frame (struct ui_file *file, stru
|
2008-12-14 14:05:20 +00:00
|
|
|
|
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;
|
2010-01-16 22:32:10 +00:00
|
|
|
|
@@ -1792,6 +1792,7 @@ get_frame_address_in_block (struct frame
|
2009-02-09 12:35:37 +00:00
|
|
|
|
{
|
|
|
|
|
/* 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;
|
|
|
|
|
|
2010-01-16 22:32:10 +00:00
|
|
|
|
@@ -1834,6 +1835,9 @@ get_frame_address_in_block (struct frame
|
2009-02-09 12:35:37 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2010-01-16 22:32:10 +00:00
|
|
|
|
@@ -1865,7 +1869,7 @@ find_frame_sal (struct frame_info *frame
|
2009-02-09 12:35:37 +00:00
|
|
|
|
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);
|
2010-01-16 22:32:10 +00:00
|
|
|
|
Index: gdb-7.0.50.20100115/gdb/breakpoint.c
|
2008-12-14 14:05:20 +00:00
|
|
|
|
===================================================================
|
2010-01-16 22:32:10 +00:00
|
|
|
|
--- gdb-7.0.50.20100115.orig/gdb/breakpoint.c 2010-01-15 11:49:49.000000000 +0100
|
|
|
|
|
+++ gdb-7.0.50.20100115/gdb/breakpoint.c 2010-01-15 11:52:20.000000000 +0100
|
2009-09-17 12:15:42 +00:00
|
|
|
|
@@ -62,6 +62,7 @@
|
2009-09-10 21:37:41 +00:00
|
|
|
|
#include "jit.h"
|
2009-09-17 12:15:42 +00:00
|
|
|
|
#include "xml-syscall.h"
|
2009-08-04 05:37:29 +00:00
|
|
|
|
#include "parser-defs.h"
|
2008-12-14 14:05:20 +00:00
|
|
|
|
+#include "inline-frame.h"
|
|
|
|
|
|
2009-08-04 05:37:29 +00:00
|
|
|
|
/* readline include files */
|
|
|
|
|
#include "readline/readline.h"
|
2010-01-16 22:32:10 +00:00
|
|
|
|
@@ -3560,10 +3561,24 @@ bpstat_check_breakpoint_conditions (bpst
|
2009-02-09 12:35:37 +00:00
|
|
|
|
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;
|
|
|
|
|
|
2010-01-16 22:32:10 +00:00
|
|
|
|
@@ -3731,6 +3746,12 @@ bpstat_stop_status (struct address_space
|
2010-01-12 22:15:57 +00:00
|
|
|
|
bs->print = 0;
|
|
|
|
|
}
|
|
|
|
|
bs->commands = copy_command_lines (bs->commands);
|
2008-12-14 14:05:20 +00:00
|
|
|
|
+
|
2010-01-12 22:15:57 +00:00
|
|
|
|
+ /* 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);
|
|
|
|
|
}
|
2008-12-14 14:05:20 +00:00
|
|
|
|
|
2010-01-16 22:32:10 +00:00
|
|
|
|
/* Print nothing for this entry if we dont stop or dont print. */
|
|
|
|
|
@@ -6039,9 +6060,9 @@ set_momentary_breakpoint (struct gdbarch
|
2009-02-09 12:35:37 +00:00
|
|
|
|
{
|
|
|
|
|
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. */
|
|
|
|
|
|
2009-08-04 05:37:29 +00:00
|
|
|
|
b = set_raw_breakpoint (gdbarch, sal, type);
|
2009-02-09 12:35:37 +00:00
|
|
|
|
b->enable_state = bp_enabled;
|
2010-01-16 22:32:10 +00:00
|
|
|
|
Index: gdb-7.0.50.20100115/gdb/inline-frame.c
|
2008-12-14 14:05:20 +00:00
|
|
|
|
===================================================================
|
2010-01-16 22:32:10 +00:00
|
|
|
|
--- gdb-7.0.50.20100115.orig/gdb/inline-frame.c 2010-01-01 08:31:36.000000000 +0100
|
|
|
|
|
+++ gdb-7.0.50.20100115/gdb/inline-frame.c 2010-01-15 11:50:59.000000000 +0100
|
|
|
|
|
@@ -213,6 +213,12 @@ inline_frame_sniffer (const struct frame
|
2008-12-14 14:05:20 +00:00
|
|
|
|
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;
|
2010-01-16 22:32:10 +00:00
|
|
|
|
@@ -222,6 +228,10 @@ inline_frame_sniffer (const struct frame
|
2008-12-14 14:05:20 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-16 22:32:10 +00:00
|
|
|
|
@@ -300,7 +310,6 @@ skip_inline_frames (ptid_t ptid)
|
2008-12-14 14:05:20 +00:00
|
|
|
|
{
|
|
|
|
|
CORE_ADDR this_pc;
|
|
|
|
|
struct block *frame_block, *cur_block;
|
|
|
|
|
- struct symbol *last_sym = NULL;
|
|
|
|
|
int skip_count = 0;
|
|
|
|
|
struct inline_state *state;
|
|
|
|
|
|
2010-01-16 22:32:10 +00:00
|
|
|
|
@@ -321,10 +330,7 @@ skip_inline_frames (ptid_t ptid)
|
2008-12-14 14:05:20 +00:00
|
|
|
|
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;
|
|
|
|
|
}
|
2010-01-16 22:32:10 +00:00
|
|
|
|
@@ -336,7 +342,6 @@ skip_inline_frames (ptid_t ptid)
|
2008-12-14 14:05:20 +00:00
|
|
|
|
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 ();
|
2010-01-16 22:32:10 +00:00
|
|
|
|
@@ -354,6 +359,23 @@ step_into_inline_frame (ptid_t ptid)
|
2009-02-09 12:35:37 +00:00
|
|
|
|
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. */
|
|
|
|
|
|
2010-01-16 22:32:10 +00:00
|
|
|
|
Index: gdb-7.0.50.20100115/gdb/testsuite/gdb.opt/inline-markers.c
|
2008-12-14 14:05:20 +00:00
|
|
|
|
===================================================================
|
2010-01-16 22:32:10 +00:00
|
|
|
|
--- gdb-7.0.50.20100115.orig/gdb/testsuite/gdb.opt/inline-markers.c 2010-01-01 08:32:04.000000000 +0100
|
|
|
|
|
+++ gdb-7.0.50.20100115/gdb/testsuite/gdb.opt/inline-markers.c 2010-01-15 11:50:59.000000000 +0100
|
2008-12-14 14:05:20 +00:00
|
|
|
|
@@ -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 */
|
2010-01-16 22:32:10 +00:00
|
|
|
|
Index: gdb-7.0.50.20100115/gdb/gdbthread.h
|
2009-02-09 12:35:37 +00:00
|
|
|
|
===================================================================
|
2010-01-16 22:32:10 +00:00
|
|
|
|
--- gdb-7.0.50.20100115.orig/gdb/gdbthread.h 2010-01-15 03:22:13.000000000 +0100
|
|
|
|
|
+++ gdb-7.0.50.20100115/gdb/gdbthread.h 2010-01-15 11:51:19.000000000 +0100
|
|
|
|
|
@@ -195,6 +195,12 @@ struct thread_info
|
|
|
|
|
/* Function that is called to free PRIVATE. If this is NULL, then
|
|
|
|
|
xfree will be called on PRIVATE. */
|
|
|
|
|
void (*private_dtor) (struct private_thread_info *);
|
2009-02-09 12:35:37 +00:00
|
|
|
|
+
|
|
|
|
|
+ /* 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. */
|
2010-01-16 22:32:10 +00:00
|
|
|
|
Index: gdb-7.0.50.20100115/gdb/infcmd.c
|
2009-02-09 12:35:37 +00:00
|
|
|
|
===================================================================
|
2010-01-16 22:32:10 +00:00
|
|
|
|
--- gdb-7.0.50.20100115.orig/gdb/infcmd.c 2010-01-15 03:22:13.000000000 +0100
|
|
|
|
|
+++ gdb-7.0.50.20100115/gdb/infcmd.c 2010-01-15 11:51:53.000000000 +0100
|
|
|
|
|
@@ -1438,11 +1438,11 @@ finish_command_continuation (void *arg)
|
2009-02-09 12:35:37 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
2010-01-16 22:32:10 +00:00
|
|
|
|
@@ -1550,6 +1550,16 @@ finish_forward (struct symbol *function,
|
2009-09-10 21:37:41 +00:00
|
|
|
|
tp->initiating_frame = get_frame_id (frame);
|
|
|
|
|
make_cleanup (delete_longjmp_breakpoint_cleanup, &thread);
|
2009-02-09 12:35:37 +00:00
|
|
|
|
|
|
|
|
|
+ /* 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... */
|
2010-01-16 22:32:10 +00:00
|
|
|
|
cargs = xmalloc (sizeof (*cargs));
|
2009-08-04 05:37:29 +00:00
|
|
|
|
|
2010-01-16 22:32:10 +00:00
|
|
|
|
@@ -1570,7 +1580,9 @@ finish_forward (struct symbol *function,
|
2009-02-09 12:35:37 +00:00
|
|
|
|
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;
|
2010-01-16 22:32:10 +00:00
|
|
|
|
@@ -1601,45 +1613,63 @@ finish_command (char *arg, int from_tty)
|
2009-02-09 12:35:37 +00:00
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
- /* 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. */
|
2009-08-04 05:37:29 +00:00
|
|
|
|
struct thread_info *tp = inferior_thread ();
|
2009-02-09 12:35:37 +00:00
|
|
|
|
struct symtab_and_line empty_sal;
|
|
|
|
|
- init_sal (&empty_sal);
|
2009-08-04 05:37:29 +00:00
|
|
|
|
- set_step_info (frame, empty_sal);
|
2009-02-09 12:35:37 +00:00
|
|
|
|
- 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);
|
2009-08-04 05:37:29 +00:00
|
|
|
|
+ }
|
|
|
|
|
+
|
2009-02-09 12:35:37 +00:00
|
|
|
|
+ /* 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;
|
2009-08-04 05:37:29 +00:00
|
|
|
|
}
|
|
|
|
|
|
2009-02-09 12:35:37 +00:00
|
|
|
|
+ /* 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);
|
2009-08-04 05:37:29 +00:00
|
|
|
|
+ set_step_info (prev_frame, empty_sal);
|
2009-02-09 12:35:37 +00:00
|
|
|
|
+ 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. */
|
2010-01-16 22:32:10 +00:00
|
|
|
|
@@ -1653,10 +1683,14 @@ finish_command (char *arg, int from_tty)
|
2009-02-09 12:35:37 +00:00
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2010-01-16 22:32:10 +00:00
|
|
|
|
Index: gdb-7.0.50.20100115/gdb/target.c
|
2009-02-09 12:35:37 +00:00
|
|
|
|
===================================================================
|
2010-01-16 22:32:10 +00:00
|
|
|
|
--- gdb-7.0.50.20100115.orig/gdb/target.c 2010-01-15 03:22:31.000000000 +0100
|
|
|
|
|
+++ gdb-7.0.50.20100115/gdb/target.c 2010-01-15 11:50:59.000000000 +0100
|
|
|
|
|
@@ -2241,6 +2241,7 @@ target_resume (ptid_t ptid, int step, en
|
2009-02-11 00:04:48 +00:00
|
|
|
|
{
|
2009-03-02 00:11:35 +00:00
|
|
|
|
struct target_ops *t;
|
|
|
|
|
|
2009-02-11 00:04:48 +00:00
|
|
|
|
+ clear_inline_frame_state (ptid);
|
2009-09-10 21:37:41 +00:00
|
|
|
|
target_dcache_invalidate ();
|
2009-03-02 00:11:35 +00:00
|
|
|
|
|
|
|
|
|
for (t = current_target.beneath; t != NULL; t = t->beneath)
|
2010-01-16 22:32:10 +00:00
|
|
|
|
Index: gdb-7.0.50.20100115/gdb/inline-frame.h
|
2009-02-09 12:35:37 +00:00
|
|
|
|
===================================================================
|
2010-01-16 22:32:10 +00:00
|
|
|
|
--- gdb-7.0.50.20100115.orig/gdb/inline-frame.h 2010-01-01 08:31:36.000000000 +0100
|
|
|
|
|
+++ gdb-7.0.50.20100115/gdb/inline-frame.h 2010-01-15 11:50:59.000000000 +0100
|
2009-02-09 12:35:37 +00:00
|
|
|
|
@@ -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. */
|
|
|
|
|
|
2010-01-16 22:32:10 +00:00
|
|
|
|
Index: gdb-7.0.50.20100115/gdb/dwarf2read.c
|
2009-03-07 00:32:30 +00:00
|
|
|
|
===================================================================
|
2010-01-16 22:32:10 +00:00
|
|
|
|
--- gdb-7.0.50.20100115.orig/gdb/dwarf2read.c 2010-01-15 11:46:29.000000000 +0100
|
|
|
|
|
+++ gdb-7.0.50.20100115/gdb/dwarf2read.c 2010-01-15 11:52:59.000000000 +0100
|
|
|
|
|
@@ -4078,6 +4078,7 @@ read_func_scope (struct die_info *die, s
|
|
|
|
|
CORE_ADDR baseaddr;
|
2009-08-04 05:37:29 +00:00
|
|
|
|
struct block *block;
|
2009-03-07 00:32:30 +00:00
|
|
|
|
int inlined_func = (die->tag == DW_TAG_inlined_subroutine);
|
|
|
|
|
+ struct type *type;
|
|
|
|
|
|
|
|
|
|
if (inlined_func)
|
|
|
|
|
{
|
2010-01-16 22:32:10 +00:00
|
|
|
|
@@ -4109,7 +4110,10 @@ read_func_scope (struct die_info *die, s
|
2009-03-07 00:32:30 +00:00
|
|
|
|
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. */
|